Death to tabs! Long live spaces!
This commit is contained in:
parent
9285836e61
commit
00faa9ec76
@ -3,7 +3,7 @@
|
||||
package="com.dougkeen.bart"
|
||||
android:installLocation="auto"
|
||||
android:versionCode="31"
|
||||
android:versionName="2.2.4" >
|
||||
android:versionName="2.2.4">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
@ -17,11 +17,11 @@
|
||||
android:name=".BartRunnerApplication_"
|
||||
android:icon="@drawable/icon"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme" >
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".activities.RoutesListActivity_"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:label="@string/app_name" >
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activities.ViewDeparturesActivity"
|
||||
android:label="@string/departures" >
|
||||
android:label="@string/departures">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
@ -58,8 +58,7 @@
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activities.ViewMapActivity"
|
||||
android:label="@string/system_map" >
|
||||
</activity>
|
||||
android:label="@string/system_map"></activity>
|
||||
|
||||
<service
|
||||
android:name=".services.BoardedDepartureService"
|
||||
@ -70,7 +69,7 @@
|
||||
|
||||
<receiver
|
||||
android:name=".receivers.AlarmBroadcastReceiver"
|
||||
android:exported="false" >
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.dougkeen.action.ALARM" />
|
||||
|
||||
|
@ -27,199 +27,199 @@ import com.googlecode.androidannotations.annotations.EApplication;
|
||||
|
||||
@EApplication
|
||||
public class BartRunnerApplication extends Application {
|
||||
private static final int FIVE_MINUTES = 5 * 60 * 1000;
|
||||
private static final int FIVE_MINUTES = 5 * 60 * 1000;
|
||||
|
||||
private static final String CACHE_FILE_NAME = "lastBoardedDeparture";
|
||||
private static final String CACHE_FILE_NAME = "lastBoardedDeparture";
|
||||
|
||||
private Departure mBoardedDeparture;
|
||||
private Departure mBoardedDeparture;
|
||||
|
||||
private boolean mPlayAlarmRingtone;
|
||||
private boolean mPlayAlarmRingtone;
|
||||
|
||||
private boolean mAlarmSounding;
|
||||
private boolean mAlarmSounding;
|
||||
|
||||
private MediaPlayer mAlarmMediaPlayer;
|
||||
private MediaPlayer mAlarmMediaPlayer;
|
||||
|
||||
private static Context context;
|
||||
private static Context context;
|
||||
|
||||
@Bean
|
||||
FavoritesPersistence favoritesPersistenceContext;
|
||||
@Bean
|
||||
FavoritesPersistence favoritesPersistenceContext;
|
||||
|
||||
private List<StationPair> favorites;
|
||||
private List<StationPair> favorites;
|
||||
|
||||
public void saveFavorites() {
|
||||
if (favorites != null) {
|
||||
favoritesPersistenceContext.persist(favorites);
|
||||
}
|
||||
}
|
||||
public void saveFavorites() {
|
||||
if (favorites != null) {
|
||||
favoritesPersistenceContext.persist(favorites);
|
||||
}
|
||||
}
|
||||
|
||||
public List<StationPair> getFavorites() {
|
||||
if (favorites == null) {
|
||||
favorites = favoritesPersistenceContext.restore();
|
||||
if (favorites.isEmpty()) {
|
||||
// Upgrade database, in case favorites are still in there
|
||||
new DatabaseHelper(this).getReadableDatabase().close();
|
||||
favorites = favoritesPersistenceContext.restore();
|
||||
}
|
||||
}
|
||||
return favorites;
|
||||
}
|
||||
public List<StationPair> getFavorites() {
|
||||
if (favorites == null) {
|
||||
favorites = favoritesPersistenceContext.restore();
|
||||
if (favorites.isEmpty()) {
|
||||
// Upgrade database, in case favorites are still in there
|
||||
new DatabaseHelper(this).getReadableDatabase().close();
|
||||
favorites = favoritesPersistenceContext.restore();
|
||||
}
|
||||
}
|
||||
return favorites;
|
||||
}
|
||||
|
||||
public void setFavorites(List<StationPair> favorites) {
|
||||
this.favorites = favorites;
|
||||
}
|
||||
public void setFavorites(List<StationPair> favorites) {
|
||||
this.favorites = favorites;
|
||||
}
|
||||
|
||||
public StationPair getFavorite(Station origin, Station destination) {
|
||||
for (StationPair favorite : getFavorites()) {
|
||||
if (origin.equals(favorite.getOrigin())
|
||||
&& destination.equals(favorite.getDestination())) {
|
||||
return favorite;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public StationPair getFavorite(Station origin, Station destination) {
|
||||
for (StationPair favorite : getFavorites()) {
|
||||
if (origin.equals(favorite.getOrigin())
|
||||
&& destination.equals(favorite.getDestination())) {
|
||||
return favorite;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addFavorite(StationPair favorite) {
|
||||
getFavorites().add(favorite);
|
||||
saveFavorites();
|
||||
}
|
||||
public void addFavorite(StationPair favorite) {
|
||||
getFavorites().add(favorite);
|
||||
saveFavorites();
|
||||
}
|
||||
|
||||
public void removeFavorite(StationPair favorite) {
|
||||
getFavorites().remove(favorite);
|
||||
saveFavorites();
|
||||
}
|
||||
public void removeFavorite(StationPair favorite) {
|
||||
getFavorites().remove(favorite);
|
||||
saveFavorites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
context = getApplicationContext();
|
||||
}
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
context = getApplicationContext();
|
||||
}
|
||||
|
||||
public static Context getAppContext() {
|
||||
return context;
|
||||
}
|
||||
public static Context getAppContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public boolean shouldPlayAlarmRingtone() {
|
||||
return mPlayAlarmRingtone;
|
||||
}
|
||||
public boolean shouldPlayAlarmRingtone() {
|
||||
return mPlayAlarmRingtone;
|
||||
}
|
||||
|
||||
public void setPlayAlarmRingtone(boolean playAlarmRingtone) {
|
||||
this.mPlayAlarmRingtone = playAlarmRingtone;
|
||||
}
|
||||
public void setPlayAlarmRingtone(boolean playAlarmRingtone) {
|
||||
this.mPlayAlarmRingtone = playAlarmRingtone;
|
||||
}
|
||||
|
||||
public Departure getBoardedDeparture() {
|
||||
return getBoardedDeparture(false);
|
||||
}
|
||||
public Departure getBoardedDeparture() {
|
||||
return getBoardedDeparture(false);
|
||||
}
|
||||
|
||||
public Departure getBoardedDeparture(boolean useOldCache) {
|
||||
if (mBoardedDeparture == null) {
|
||||
// see if there's a saved one
|
||||
File cachedDepartureFile = new File(getCacheDir(), CACHE_FILE_NAME);
|
||||
if (cachedDepartureFile.exists()) {
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = new FileInputStream(cachedDepartureFile);
|
||||
final byte[] byteArray = IOUtils.toByteArray(inputStream);
|
||||
final Parcel parcel = Parcel.obtain();
|
||||
parcel.unmarshall(byteArray, 0, byteArray.length);
|
||||
parcel.setDataPosition(0);
|
||||
Departure lastBoardedDeparture = Departure.CREATOR
|
||||
.createFromParcel(parcel);
|
||||
parcel.recycle();
|
||||
public Departure getBoardedDeparture(boolean useOldCache) {
|
||||
if (mBoardedDeparture == null) {
|
||||
// see if there's a saved one
|
||||
File cachedDepartureFile = new File(getCacheDir(), CACHE_FILE_NAME);
|
||||
if (cachedDepartureFile.exists()) {
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = new FileInputStream(cachedDepartureFile);
|
||||
final byte[] byteArray = IOUtils.toByteArray(inputStream);
|
||||
final Parcel parcel = Parcel.obtain();
|
||||
parcel.unmarshall(byteArray, 0, byteArray.length);
|
||||
parcel.setDataPosition(0);
|
||||
Departure lastBoardedDeparture = Departure.CREATOR
|
||||
.createFromParcel(parcel);
|
||||
parcel.recycle();
|
||||
|
||||
/*
|
||||
* Ooptionally check if the cached one is relatively recent.
|
||||
* Ooptionally check if the cached one is relatively recent.
|
||||
* If so, restore that to the application context
|
||||
*/
|
||||
long now = System.currentTimeMillis();
|
||||
if (useOldCache
|
||||
|| lastBoardedDeparture.getEstimatedArrivalTime() >= now
|
||||
- FIVE_MINUTES
|
||||
|| lastBoardedDeparture.getMeanEstimate() >= now
|
||||
- 2 * FIVE_MINUTES) {
|
||||
mBoardedDeparture = lastBoardedDeparture;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.w(Constants.TAG,
|
||||
"Couldn't read or unmarshal lastBoardedDeparture file",
|
||||
e);
|
||||
try {
|
||||
cachedDepartureFile.delete();
|
||||
} catch (SecurityException anotherException) {
|
||||
Log.w(Constants.TAG,
|
||||
"Couldn't delete lastBoardedDeparture file",
|
||||
anotherException);
|
||||
}
|
||||
} finally {
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mBoardedDeparture != null && mBoardedDeparture.hasExpired()) {
|
||||
setBoardedDeparture(null);
|
||||
}
|
||||
return mBoardedDeparture;
|
||||
}
|
||||
long now = System.currentTimeMillis();
|
||||
if (useOldCache
|
||||
|| lastBoardedDeparture.getEstimatedArrivalTime() >= now
|
||||
- FIVE_MINUTES
|
||||
|| lastBoardedDeparture.getMeanEstimate() >= now
|
||||
- 2 * FIVE_MINUTES) {
|
||||
mBoardedDeparture = lastBoardedDeparture;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.w(Constants.TAG,
|
||||
"Couldn't read or unmarshal lastBoardedDeparture file",
|
||||
e);
|
||||
try {
|
||||
cachedDepartureFile.delete();
|
||||
} catch (SecurityException anotherException) {
|
||||
Log.w(Constants.TAG,
|
||||
"Couldn't delete lastBoardedDeparture file",
|
||||
anotherException);
|
||||
}
|
||||
} finally {
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mBoardedDeparture != null && mBoardedDeparture.hasExpired()) {
|
||||
setBoardedDeparture(null);
|
||||
}
|
||||
return mBoardedDeparture;
|
||||
}
|
||||
|
||||
public void setBoardedDeparture(Departure boardedDeparture) {
|
||||
if (!ObjectUtils.equals(boardedDeparture, mBoardedDeparture)
|
||||
|| ObjectUtils.compare(mBoardedDeparture, boardedDeparture) != 0) {
|
||||
if (this.mBoardedDeparture != null) {
|
||||
this.mBoardedDeparture.getAlarmLeadTimeMinutesObservable()
|
||||
.unregisterAllObservers();
|
||||
this.mBoardedDeparture.getAlarmPendingObservable()
|
||||
.unregisterAllObservers();
|
||||
public void setBoardedDeparture(Departure boardedDeparture) {
|
||||
if (!ObjectUtils.equals(boardedDeparture, mBoardedDeparture)
|
||||
|| ObjectUtils.compare(mBoardedDeparture, boardedDeparture) != 0) {
|
||||
if (this.mBoardedDeparture != null) {
|
||||
this.mBoardedDeparture.getAlarmLeadTimeMinutesObservable()
|
||||
.unregisterAllObservers();
|
||||
this.mBoardedDeparture.getAlarmPendingObservable()
|
||||
.unregisterAllObservers();
|
||||
|
||||
// Cancel any pending alarms for the current departure
|
||||
if (this.mBoardedDeparture.isAlarmPending()) {
|
||||
this.mBoardedDeparture
|
||||
.cancelAlarm(
|
||||
this,
|
||||
(AlarmManager) getSystemService(Context.ALARM_SERVICE));
|
||||
}
|
||||
}
|
||||
// Cancel any pending alarms for the current departure
|
||||
if (this.mBoardedDeparture.isAlarmPending()) {
|
||||
this.mBoardedDeparture
|
||||
.cancelAlarm(
|
||||
this,
|
||||
(AlarmManager) getSystemService(Context.ALARM_SERVICE));
|
||||
}
|
||||
}
|
||||
|
||||
this.mBoardedDeparture = boardedDeparture;
|
||||
this.mBoardedDeparture = boardedDeparture;
|
||||
|
||||
File cachedDepartureFile = new File(getCacheDir(), CACHE_FILE_NAME);
|
||||
if (mBoardedDeparture == null) {
|
||||
try {
|
||||
cachedDepartureFile.delete();
|
||||
} catch (SecurityException anotherException) {
|
||||
Log.w(Constants.TAG,
|
||||
"Couldn't delete lastBoardedDeparture file",
|
||||
anotherException);
|
||||
}
|
||||
} else {
|
||||
FileOutputStream fileOutputStream = null;
|
||||
try {
|
||||
fileOutputStream = new FileOutputStream(cachedDepartureFile);
|
||||
Parcel parcel = Parcel.obtain();
|
||||
mBoardedDeparture.writeToParcel(parcel, 0);
|
||||
fileOutputStream.write(parcel.marshall());
|
||||
} catch (Exception e) {
|
||||
Log.w(Constants.TAG,
|
||||
"Couldn't write last boarded departure cache file",
|
||||
e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(fileOutputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File cachedDepartureFile = new File(getCacheDir(), CACHE_FILE_NAME);
|
||||
if (mBoardedDeparture == null) {
|
||||
try {
|
||||
cachedDepartureFile.delete();
|
||||
} catch (SecurityException anotherException) {
|
||||
Log.w(Constants.TAG,
|
||||
"Couldn't delete lastBoardedDeparture file",
|
||||
anotherException);
|
||||
}
|
||||
} else {
|
||||
FileOutputStream fileOutputStream = null;
|
||||
try {
|
||||
fileOutputStream = new FileOutputStream(cachedDepartureFile);
|
||||
Parcel parcel = Parcel.obtain();
|
||||
mBoardedDeparture.writeToParcel(parcel, 0);
|
||||
fileOutputStream.write(parcel.marshall());
|
||||
} catch (Exception e) {
|
||||
Log.w(Constants.TAG,
|
||||
"Couldn't write last boarded departure cache file",
|
||||
e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(fileOutputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAlarmSounding() {
|
||||
return mAlarmSounding;
|
||||
}
|
||||
public boolean isAlarmSounding() {
|
||||
return mAlarmSounding;
|
||||
}
|
||||
|
||||
public void setAlarmSounding(boolean alarmSounding) {
|
||||
this.mAlarmSounding = alarmSounding;
|
||||
}
|
||||
public void setAlarmSounding(boolean alarmSounding) {
|
||||
this.mAlarmSounding = alarmSounding;
|
||||
}
|
||||
|
||||
public MediaPlayer getAlarmMediaPlayer() {
|
||||
return mAlarmMediaPlayer;
|
||||
}
|
||||
public MediaPlayer getAlarmMediaPlayer() {
|
||||
return mAlarmMediaPlayer;
|
||||
}
|
||||
|
||||
public void setAlarmMediaPlayer(MediaPlayer alarmMediaPlayer) {
|
||||
this.mAlarmMediaPlayer = alarmMediaPlayer;
|
||||
}
|
||||
public void setAlarmMediaPlayer(MediaPlayer alarmMediaPlayer) {
|
||||
this.mAlarmMediaPlayer = alarmMediaPlayer;
|
||||
}
|
||||
}
|
||||
|
@ -21,132 +21,132 @@ import com.dougkeen.bart.model.Station;
|
||||
|
||||
public abstract class AbstractRouteSelectionFragment extends DialogFragment {
|
||||
|
||||
private static final String KEY_LAST_SELECTED_DESTINATION = "lastSelectedDestination";
|
||||
private static final String KEY_LAST_SELECTED_ORIGIN = "lastSelectedOrigin";
|
||||
protected String mTitle;
|
||||
private static final String KEY_LAST_SELECTED_DESTINATION = "lastSelectedDestination";
|
||||
private static final String KEY_LAST_SELECTED_ORIGIN = "lastSelectedOrigin";
|
||||
protected String mTitle;
|
||||
|
||||
public AbstractRouteSelectionFragment(String title) {
|
||||
super();
|
||||
mTitle = title;
|
||||
}
|
||||
public AbstractRouteSelectionFragment(String title) {
|
||||
super();
|
||||
mTitle = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setArguments(Bundle args) {
|
||||
super.setArguments(args);
|
||||
if (args.containsKey("title"))
|
||||
mTitle = args.getString("title");
|
||||
}
|
||||
@Override
|
||||
public void setArguments(Bundle args) {
|
||||
super.setArguments(args);
|
||||
if (args.containsKey("title"))
|
||||
mTitle = args.getString("title");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setShowsDialog(true);
|
||||
}
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setShowsDialog(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
SharedPreferences preferences = getActivity().getPreferences(
|
||||
Context.MODE_PRIVATE);
|
||||
SharedPreferences preferences = getActivity().getPreferences(
|
||||
Context.MODE_PRIVATE);
|
||||
|
||||
final int lastSelectedOriginPosition = preferences.getInt(
|
||||
KEY_LAST_SELECTED_ORIGIN, 0);
|
||||
final int lastSelectedDestinationPosition = preferences.getInt(
|
||||
KEY_LAST_SELECTED_DESTINATION, 1);
|
||||
final int lastSelectedOriginPosition = preferences.getInt(
|
||||
KEY_LAST_SELECTED_ORIGIN, 0);
|
||||
final int lastSelectedDestinationPosition = preferences.getInt(
|
||||
KEY_LAST_SELECTED_DESTINATION, 1);
|
||||
|
||||
final Dialog dialog = getDialog();
|
||||
final FragmentActivity activity = getActivity();
|
||||
ArrayAdapter<Station> originSpinnerAdapter = new ArrayAdapter<Station>(
|
||||
activity, R.layout.simple_spinner_item,
|
||||
Station.getStationList());
|
||||
originSpinnerAdapter
|
||||
.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
|
||||
final Dialog dialog = getDialog();
|
||||
final FragmentActivity activity = getActivity();
|
||||
ArrayAdapter<Station> originSpinnerAdapter = new ArrayAdapter<Station>(
|
||||
activity, R.layout.simple_spinner_item,
|
||||
Station.getStationList());
|
||||
originSpinnerAdapter
|
||||
.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
|
||||
|
||||
final Spinner originSpinner = (Spinner) dialog
|
||||
.findViewById(R.id.origin_spinner);
|
||||
originSpinner.setAdapter(originSpinnerAdapter);
|
||||
originSpinner.setSelection(lastSelectedOriginPosition);
|
||||
final Spinner originSpinner = (Spinner) dialog
|
||||
.findViewById(R.id.origin_spinner);
|
||||
originSpinner.setAdapter(originSpinnerAdapter);
|
||||
originSpinner.setSelection(lastSelectedOriginPosition);
|
||||
|
||||
ArrayAdapter<Station> destinationSpinnerAdapter = new ArrayAdapter<Station>(
|
||||
activity, R.layout.simple_spinner_item,
|
||||
Station.getStationList());
|
||||
destinationSpinnerAdapter
|
||||
.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
|
||||
ArrayAdapter<Station> destinationSpinnerAdapter = new ArrayAdapter<Station>(
|
||||
activity, R.layout.simple_spinner_item,
|
||||
Station.getStationList());
|
||||
destinationSpinnerAdapter
|
||||
.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
|
||||
|
||||
final Spinner destinationSpinner = (Spinner) dialog
|
||||
.findViewById(R.id.destination_spinner);
|
||||
destinationSpinner.setAdapter(destinationSpinnerAdapter);
|
||||
destinationSpinner.setSelection(lastSelectedDestinationPosition);
|
||||
}
|
||||
final Spinner destinationSpinner = (Spinner) dialog
|
||||
.findViewById(R.id.destination_spinner);
|
||||
destinationSpinner.setAdapter(destinationSpinnerAdapter);
|
||||
destinationSpinner.setSelection(lastSelectedDestinationPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final FragmentActivity activity = getActivity();
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final FragmentActivity activity = getActivity();
|
||||
|
||||
final View dialogView = LayoutInflater.inflate(activity,
|
||||
R.layout.route_form);
|
||||
final View dialogView = LayoutInflater.inflate(activity,
|
||||
R.layout.route_form);
|
||||
|
||||
return new AlertDialog.Builder(activity)
|
||||
.setTitle(mTitle)
|
||||
.setCancelable(true)
|
||||
.setView(dialogView)
|
||||
.setPositiveButton(R.string.ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
handleOkClick();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog,
|
||||
int whichButton) {
|
||||
dialog.cancel();
|
||||
}
|
||||
}).create();
|
||||
}
|
||||
return new AlertDialog.Builder(activity)
|
||||
.setTitle(mTitle)
|
||||
.setCancelable(true)
|
||||
.setView(dialogView)
|
||||
.setPositiveButton(R.string.ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
handleOkClick();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog,
|
||||
int whichButton) {
|
||||
dialog.cancel();
|
||||
}
|
||||
}).create();
|
||||
}
|
||||
|
||||
protected void handleOkClick() {
|
||||
final Dialog dialog = getDialog();
|
||||
final Spinner originSpinner = (Spinner) dialog
|
||||
.findViewById(R.id.origin_spinner);
|
||||
final Spinner destinationSpinner = (Spinner) dialog
|
||||
.findViewById(R.id.destination_spinner);
|
||||
protected void handleOkClick() {
|
||||
final Dialog dialog = getDialog();
|
||||
final Spinner originSpinner = (Spinner) dialog
|
||||
.findViewById(R.id.origin_spinner);
|
||||
final Spinner destinationSpinner = (Spinner) dialog
|
||||
.findViewById(R.id.destination_spinner);
|
||||
|
||||
Station origin = (Station) originSpinner.getSelectedItem();
|
||||
Station destination = (Station) destinationSpinner.getSelectedItem();
|
||||
if (origin == null) {
|
||||
Toast.makeText(dialog.getContext(),
|
||||
com.dougkeen.bart.R.string.error_null_origin,
|
||||
Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
if (destination == null) {
|
||||
Toast.makeText(dialog.getContext(),
|
||||
com.dougkeen.bart.R.string.error_null_destination,
|
||||
Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
if (origin.equals(destination)) {
|
||||
Toast.makeText(
|
||||
dialog.getContext(),
|
||||
com.dougkeen.bart.R.string.error_matching_origin_and_destination,
|
||||
Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
Station origin = (Station) originSpinner.getSelectedItem();
|
||||
Station destination = (Station) destinationSpinner.getSelectedItem();
|
||||
if (origin == null) {
|
||||
Toast.makeText(dialog.getContext(),
|
||||
com.dougkeen.bart.R.string.error_null_origin,
|
||||
Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
if (destination == null) {
|
||||
Toast.makeText(dialog.getContext(),
|
||||
com.dougkeen.bart.R.string.error_null_destination,
|
||||
Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
if (origin.equals(destination)) {
|
||||
Toast.makeText(
|
||||
dialog.getContext(),
|
||||
com.dougkeen.bart.R.string.error_matching_origin_and_destination,
|
||||
Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
final Editor prefsEditor = getActivity().getPreferences(
|
||||
Context.MODE_PRIVATE).edit();
|
||||
prefsEditor.putInt(KEY_LAST_SELECTED_ORIGIN,
|
||||
originSpinner.getSelectedItemPosition());
|
||||
prefsEditor.putInt(KEY_LAST_SELECTED_DESTINATION,
|
||||
destinationSpinner.getSelectedItemPosition());
|
||||
prefsEditor.commit();
|
||||
final Editor prefsEditor = getActivity().getPreferences(
|
||||
Context.MODE_PRIVATE).edit();
|
||||
prefsEditor.putInt(KEY_LAST_SELECTED_ORIGIN,
|
||||
originSpinner.getSelectedItemPosition());
|
||||
prefsEditor.putInt(KEY_LAST_SELECTED_DESTINATION,
|
||||
destinationSpinner.getSelectedItemPosition());
|
||||
prefsEditor.commit();
|
||||
|
||||
onOkButtonClick(origin, destination);
|
||||
}
|
||||
onOkButtonClick(origin, destination);
|
||||
}
|
||||
|
||||
abstract protected void onOkButtonClick(Station origin, Station destination);
|
||||
abstract protected void onOkButtonClick(Station origin, Station destination);
|
||||
}
|
||||
|
@ -9,29 +9,29 @@ import com.dougkeen.bart.model.Station;
|
||||
import com.dougkeen.bart.model.StationPair;
|
||||
|
||||
public class AddRouteDialogFragment extends AbstractRouteSelectionFragment {
|
||||
public AddRouteDialogFragment() {
|
||||
super(BartRunnerApplication.getAppContext().getString(
|
||||
R.string.add_route));
|
||||
}
|
||||
public AddRouteDialogFragment() {
|
||||
super(BartRunnerApplication.getAppContext().getString(
|
||||
R.string.add_route));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
final View checkbox = getDialog().findViewById(R.id.return_checkbox);
|
||||
checkbox.setVisibility(View.VISIBLE);
|
||||
}
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
final View checkbox = getDialog().findViewById(R.id.return_checkbox);
|
||||
checkbox.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onOkButtonClick(Station origin, Station destination) {
|
||||
RoutesListActivity activity = (RoutesListActivity) getActivity();
|
||||
activity.addFavorite(new StationPair(origin, destination));
|
||||
@Override
|
||||
protected void onOkButtonClick(Station origin, Station destination) {
|
||||
RoutesListActivity activity = (RoutesListActivity) getActivity();
|
||||
activity.addFavorite(new StationPair(origin, destination));
|
||||
|
||||
if (((CheckBox) getDialog().findViewById(R.id.return_checkbox))
|
||||
.isChecked()) {
|
||||
activity.addFavorite(new StationPair(destination, origin));
|
||||
}
|
||||
if (((CheckBox) getDialog().findViewById(R.id.return_checkbox))
|
||||
.isChecked()) {
|
||||
activity.addFavorite(new StationPair(destination, origin));
|
||||
}
|
||||
|
||||
dismiss();
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,16 +10,16 @@ import com.dougkeen.bart.model.StationPair;
|
||||
|
||||
public class QuickRouteDialogFragment extends AbstractRouteSelectionFragment {
|
||||
|
||||
public QuickRouteDialogFragment() {
|
||||
super(BartRunnerApplication.getAppContext().getString(
|
||||
R.string.quick_departure_lookup));
|
||||
}
|
||||
public QuickRouteDialogFragment() {
|
||||
super(BartRunnerApplication.getAppContext().getString(
|
||||
R.string.quick_departure_lookup));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onOkButtonClick(Station origin, Station destination) {
|
||||
Intent intent = new Intent(getActivity(), ViewDeparturesActivity.class);
|
||||
intent.putExtra(Constants.STATION_PAIR_EXTRA, new StationPair(origin,
|
||||
destination));
|
||||
startActivity(intent);
|
||||
}
|
||||
@Override
|
||||
protected void onOkButtonClick(Station origin, Station destination) {
|
||||
Intent intent = new Intent(getActivity(), ViewDeparturesActivity.class);
|
||||
intent.putExtra(Constants.STATION_PAIR_EXTRA, new StationPair(origin,
|
||||
destination));
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
@ -50,398 +50,400 @@ import com.mobeta.android.dslv.DragSortListView;
|
||||
|
||||
@EActivity(R.layout.main)
|
||||
public class RoutesListActivity extends Activity implements TickSubscriber {
|
||||
private static final String NO_DELAYS_REPORTED = "No delays reported";
|
||||
private static final String NO_DELAYS_REPORTED = "No delays reported";
|
||||
|
||||
private static final TimeZone PACIFIC_TIME = TimeZone
|
||||
.getTimeZone("America/Los_Angeles");
|
||||
private static final TimeZone PACIFIC_TIME = TimeZone
|
||||
.getTimeZone("America/Los_Angeles");
|
||||
|
||||
private static final String TAG = "RoutesListActivity";
|
||||
private static final String TAG = "RoutesListActivity";
|
||||
|
||||
@InstanceState
|
||||
StationPair mCurrentlySelectedStationPair;
|
||||
@InstanceState
|
||||
StationPair mCurrentlySelectedStationPair;
|
||||
|
||||
@InstanceState
|
||||
String mCurrentAlerts;
|
||||
@InstanceState
|
||||
String mCurrentAlerts;
|
||||
|
||||
private ActionMode mActionMode;
|
||||
private ActionMode mActionMode;
|
||||
|
||||
private FavoritesArrayAdapter mRoutesAdapter;
|
||||
private FavoritesArrayAdapter mRoutesAdapter;
|
||||
|
||||
@App
|
||||
BartRunnerApplication app;
|
||||
@App
|
||||
BartRunnerApplication app;
|
||||
|
||||
@RestService
|
||||
AlertsClient alertsClient;
|
||||
@RestService
|
||||
AlertsClient alertsClient;
|
||||
|
||||
@RestService
|
||||
ElevatorClient elevatorClient;
|
||||
@RestService
|
||||
ElevatorClient elevatorClient;
|
||||
|
||||
@ViewById(android.R.id.list)
|
||||
DragSortListView listView;
|
||||
@ViewById(android.R.id.list)
|
||||
DragSortListView listView;
|
||||
|
||||
@ViewById(R.id.quickLookupButton)
|
||||
Button quickLookupButton;
|
||||
@ViewById(R.id.quickLookupButton)
|
||||
Button quickLookupButton;
|
||||
|
||||
@ViewById(R.id.alertMessages)
|
||||
TextView alertMessages;
|
||||
@ViewById(R.id.alertMessages)
|
||||
TextView alertMessages;
|
||||
|
||||
@Click(R.id.quickLookupButton)
|
||||
void quickLookupButtonClick() {
|
||||
DialogFragment dialog = new QuickRouteDialogFragment();
|
||||
dialog.show(getSupportFragmentManager().beginTransaction());
|
||||
}
|
||||
@Click(R.id.quickLookupButton)
|
||||
void quickLookupButtonClick() {
|
||||
DialogFragment dialog = new QuickRouteDialogFragment();
|
||||
dialog.show(getSupportFragmentManager().beginTransaction());
|
||||
}
|
||||
|
||||
@ItemClick(android.R.id.list)
|
||||
void listItemClicked(StationPair item) {
|
||||
Intent intent = new Intent(RoutesListActivity.this,
|
||||
ViewDeparturesActivity.class);
|
||||
intent.putExtra(Constants.STATION_PAIR_EXTRA, item);
|
||||
startActivity(intent);
|
||||
}
|
||||
@ItemClick(android.R.id.list)
|
||||
void listItemClicked(StationPair item) {
|
||||
Intent intent = new Intent(RoutesListActivity.this,
|
||||
ViewDeparturesActivity.class);
|
||||
intent.putExtra(Constants.STATION_PAIR_EXTRA, item);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
@ItemLongClick(android.R.id.list)
|
||||
void listItemLongClick(StationPair item) {
|
||||
if (mActionMode != null) {
|
||||
mActionMode.finish();
|
||||
}
|
||||
@ItemLongClick(android.R.id.list)
|
||||
void listItemLongClick(StationPair item) {
|
||||
if (mActionMode != null) {
|
||||
mActionMode.finish();
|
||||
}
|
||||
|
||||
mCurrentlySelectedStationPair = item;
|
||||
mCurrentlySelectedStationPair = item;
|
||||
|
||||
startContextualActionMode();
|
||||
}
|
||||
startContextualActionMode();
|
||||
}
|
||||
|
||||
private DragSortListView.DropListener onDrop = new DragSortListView.DropListener() {
|
||||
@Override
|
||||
public void drop(int from, int to) {
|
||||
if (from == to)
|
||||
return;
|
||||
|
||||
StationPair item = mRoutesAdapter.getItem(from);
|
||||
|
||||
mRoutesAdapter.move(item, to);
|
||||
mRoutesAdapter.notifyDataSetChanged();
|
||||
}
|
||||
};
|
||||
|
||||
private DragSortListView.RemoveListener onRemove = new DragSortListView.RemoveListener() {
|
||||
@Override
|
||||
public void remove(int which) {
|
||||
mRoutesAdapter.remove(mRoutesAdapter.getItem(which));
|
||||
mRoutesAdapter.notifyDataSetChanged();
|
||||
}
|
||||
};
|
||||
|
||||
@AfterViews
|
||||
void afterViews() {
|
||||
setTitle(R.string.favorite_routes);
|
||||
|
||||
mRoutesAdapter = new FavoritesArrayAdapter(this,
|
||||
R.layout.favorite_listing, app.getFavorites());
|
||||
|
||||
setListAdapter(mRoutesAdapter);
|
||||
|
||||
listView.setEmptyView(findViewById(android.R.id.empty));
|
||||
|
||||
listView.setDropListener(onDrop);
|
||||
listView.setRemoveListener(onRemove);
|
||||
|
||||
if (mCurrentAlerts != null) {
|
||||
showAlertMessage(mCurrentAlerts);
|
||||
}
|
||||
|
||||
startEtdListeners();
|
||||
refreshFares();
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
if (savedInstanceState.getBoolean("hasActionMode")) {
|
||||
startContextualActionMode();
|
||||
}
|
||||
}
|
||||
|
||||
Ticker.getInstance().addSubscriber(this, getApplicationContext());
|
||||
}
|
||||
|
||||
private AdapterView<ListAdapter> getListView() {
|
||||
return listView;
|
||||
}
|
||||
|
||||
protected FavoritesArrayAdapter getListAdapter() {
|
||||
return mRoutesAdapter;
|
||||
}
|
||||
|
||||
protected void setListAdapter(FavoritesArrayAdapter adapter) {
|
||||
mRoutesAdapter = adapter;
|
||||
getListView().setAdapter(mRoutesAdapter);
|
||||
}
|
||||
|
||||
void addFavorite(StationPair pair) {
|
||||
mRoutesAdapter.add(pair);
|
||||
}
|
||||
|
||||
private void refreshFares() {
|
||||
for (int i = getListAdapter().getCount() - 1; i >= 0; i--) {
|
||||
final StationPair stationPair = getListAdapter().getItem(i);
|
||||
|
||||
Calendar now = Calendar.getInstance();
|
||||
Calendar lastUpdate = Calendar.getInstance();
|
||||
lastUpdate.setTimeInMillis(stationPair.getFareLastUpdated());
|
||||
|
||||
now.setTimeZone(PACIFIC_TIME);
|
||||
lastUpdate.setTimeZone(PACIFIC_TIME);
|
||||
|
||||
// Update every day
|
||||
if (now.get(Calendar.DAY_OF_YEAR) != lastUpdate
|
||||
.get(Calendar.DAY_OF_YEAR)
|
||||
|| now.get(Calendar.YEAR) != lastUpdate.get(Calendar.YEAR)) {
|
||||
GetRouteFareTask fareTask = new GetRouteFareTask() {
|
||||
@Override
|
||||
public void onResult(String fare) {
|
||||
stationPair.setFare(fare);
|
||||
stationPair.setFareLastUpdated(System
|
||||
.currentTimeMillis());
|
||||
getListAdapter().notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Exception exception) {
|
||||
// Ignore... we can do this later
|
||||
}
|
||||
};
|
||||
fareTask.execute(new GetRouteFareTask.Params(stationPair
|
||||
.getOrigin(), stationPair.getDestination()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putBoolean("hasActionMode", mActionMode != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
Ticker.getInstance().startTicking(this);
|
||||
startEtdListeners();
|
||||
}
|
||||
|
||||
private void startEtdListeners() {
|
||||
if (mRoutesAdapter != null && !mRoutesAdapter.isEmpty()
|
||||
&& !mRoutesAdapter.areEtdListenersActive()) {
|
||||
mRoutesAdapter.setUpEtdListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
if (mRoutesAdapter != null && mRoutesAdapter.areEtdListenersActive()) {
|
||||
mRoutesAdapter.clearEtdListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
Ticker.getInstance().stopTicking(this);
|
||||
app.saveFavorites();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mRoutesAdapter != null) {
|
||||
mRoutesAdapter.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
if (hasFocus) {
|
||||
Ticker.getInstance().startTicking(this);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getSupportMenuInflater();
|
||||
inflater.inflate(R.menu.routes_list_menu, menu);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
private MenuItem elevatorMenuItem;
|
||||
private View origElevatorActionView;
|
||||
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int itemId = item.getItemId();
|
||||
if (itemId == R.id.add_favorite_menu_button) {
|
||||
new AddRouteDialogFragment().show(getSupportFragmentManager()
|
||||
.beginTransaction());
|
||||
return true;
|
||||
} else if (itemId == R.id.view_system_map_button) {
|
||||
startActivity(new Intent(this, ViewMapActivity.class));
|
||||
return true;
|
||||
} else if (itemId == R.id.elevator_button) {
|
||||
elevatorMenuItem = item;
|
||||
fetchElevatorInfo();
|
||||
origElevatorActionView = elevatorMenuItem.getActionView();
|
||||
elevatorMenuItem.setActionView(R.layout.progress_spinner);
|
||||
return true;
|
||||
} else {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Background
|
||||
void fetchAlerts() {
|
||||
Log.d(TAG, "Fetching alerts");
|
||||
AlertList alertList = alertsClient.getAlerts();
|
||||
if (alertList.hasAlerts()) {
|
||||
StringBuilder alertText = new StringBuilder();
|
||||
boolean firstAlert = true;
|
||||
for (Alert alert : alertList.getAlerts()) {
|
||||
if (!firstAlert) {
|
||||
alertText.append("\n\n");
|
||||
}
|
||||
alertText.append(alert.getPostedTime()).append("\n");
|
||||
alertText.append(alert.getDescription());
|
||||
firstAlert = false;
|
||||
}
|
||||
showAlertMessage(alertText.toString());
|
||||
} else if (alertList.areNoDelaysReported()) {
|
||||
showAlertMessage(NO_DELAYS_REPORTED);
|
||||
} else {
|
||||
hideAlertMessage();
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
void hideAlertMessage() {
|
||||
mCurrentAlerts = null;
|
||||
alertMessages.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
void showAlertMessage(String messageText) {
|
||||
if (messageText == null) {
|
||||
hideAlertMessage();
|
||||
return;
|
||||
} else if (messageText == NO_DELAYS_REPORTED) {
|
||||
alertMessages.setCompoundDrawablesWithIntrinsicBounds(
|
||||
R.drawable.ic_allgood, 0, 0, 0);
|
||||
} else {
|
||||
alertMessages.setCompoundDrawablesWithIntrinsicBounds(
|
||||
R.drawable.ic_warn, 0, 0, 0);
|
||||
}
|
||||
mCurrentAlerts = messageText;
|
||||
alertMessages.setText(messageText);
|
||||
alertMessages.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Background
|
||||
void fetchElevatorInfo() {
|
||||
String elevatorMessage = elevatorClient.getElevatorMessage();
|
||||
if (elevatorMessage != null) {
|
||||
showElevatorMessage(elevatorMessage);
|
||||
}
|
||||
resetElevatorMenuGraphic();
|
||||
}
|
||||
|
||||
@UiThread
|
||||
void resetElevatorMenuGraphic() {
|
||||
ActivityCompat.invalidateOptionsMenu(this);
|
||||
elevatorMenuItem.setActionView(origElevatorActionView);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
void showElevatorMessage(String message) {
|
||||
Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setMessage(message);
|
||||
builder.setTitle("Elevator status");
|
||||
builder.show();
|
||||
}
|
||||
|
||||
private void startContextualActionMode() {
|
||||
mActionMode = startActionMode(new RouteActionMode());
|
||||
mActionMode.setTitle(mCurrentlySelectedStationPair.getOrigin().name);
|
||||
mActionMode.setSubtitle("to "
|
||||
+ mCurrentlySelectedStationPair.getDestination().name);
|
||||
}
|
||||
|
||||
private final class RouteActionMode implements ActionMode.Callback {
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
mode.getMenuInflater().inflate(R.menu.route_context_menu, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
||||
if (item.getItemId() == R.id.view) {
|
||||
Intent intent = new Intent(RoutesListActivity.this,
|
||||
ViewDeparturesActivity.class);
|
||||
intent.putExtra(Constants.STATION_PAIR_EXTRA,
|
||||
mCurrentlySelectedStationPair);
|
||||
startActivity(intent);
|
||||
mode.finish();
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.delete) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(
|
||||
RoutesListActivity.this);
|
||||
builder.setCancelable(false);
|
||||
builder.setMessage("Are you sure you want to delete this route?");
|
||||
builder.setPositiveButton(R.string.yes,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
getListAdapter().remove(
|
||||
mCurrentlySelectedStationPair);
|
||||
mCurrentlySelectedStationPair = null;
|
||||
mActionMode.finish();
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
dialog.cancel();
|
||||
}
|
||||
});
|
||||
builder.show();
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyActionMode(ActionMode mode) {
|
||||
mActionMode = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTickInterval() {
|
||||
return 90;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick(long mTickCount) {
|
||||
fetchAlerts();
|
||||
}
|
||||
private DragSortListView.DropListener onDrop = new DragSortListView.DropListener() {
|
||||
@Override
|
||||
public void drop(int from, int to) {
|
||||
if (from == to)
|
||||
return;
|
||||
|
||||
StationPair item = mRoutesAdapter.getItem(from);
|
||||
|
||||
mRoutesAdapter.move(item, to);
|
||||
mRoutesAdapter.notifyDataSetChanged();
|
||||
}
|
||||
};
|
||||
|
||||
private DragSortListView.RemoveListener onRemove = new DragSortListView.RemoveListener() {
|
||||
@Override
|
||||
public void remove(int which) {
|
||||
mRoutesAdapter.remove(mRoutesAdapter.getItem(which));
|
||||
mRoutesAdapter.notifyDataSetChanged();
|
||||
}
|
||||
};
|
||||
|
||||
@AfterViews
|
||||
void afterViews() {
|
||||
setTitle(R.string.favorite_routes);
|
||||
|
||||
mRoutesAdapter = new FavoritesArrayAdapter(this,
|
||||
R.layout.favorite_listing, app.getFavorites());
|
||||
|
||||
setListAdapter(mRoutesAdapter);
|
||||
|
||||
listView.setEmptyView(findViewById(android.R.id.empty));
|
||||
|
||||
listView.setDropListener(onDrop);
|
||||
listView.setRemoveListener(onRemove);
|
||||
|
||||
if (mCurrentAlerts != null) {
|
||||
showAlertMessage(mCurrentAlerts);
|
||||
}
|
||||
|
||||
startEtdListeners();
|
||||
refreshFares();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the activity is first created.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
if (savedInstanceState.getBoolean("hasActionMode")) {
|
||||
startContextualActionMode();
|
||||
}
|
||||
}
|
||||
|
||||
Ticker.getInstance().addSubscriber(this, getApplicationContext());
|
||||
}
|
||||
|
||||
private AdapterView<ListAdapter> getListView() {
|
||||
return listView;
|
||||
}
|
||||
|
||||
protected FavoritesArrayAdapter getListAdapter() {
|
||||
return mRoutesAdapter;
|
||||
}
|
||||
|
||||
protected void setListAdapter(FavoritesArrayAdapter adapter) {
|
||||
mRoutesAdapter = adapter;
|
||||
getListView().setAdapter(mRoutesAdapter);
|
||||
}
|
||||
|
||||
void addFavorite(StationPair pair) {
|
||||
mRoutesAdapter.add(pair);
|
||||
}
|
||||
|
||||
private void refreshFares() {
|
||||
for (int i = getListAdapter().getCount() - 1; i >= 0; i--) {
|
||||
final StationPair stationPair = getListAdapter().getItem(i);
|
||||
|
||||
Calendar now = Calendar.getInstance();
|
||||
Calendar lastUpdate = Calendar.getInstance();
|
||||
lastUpdate.setTimeInMillis(stationPair.getFareLastUpdated());
|
||||
|
||||
now.setTimeZone(PACIFIC_TIME);
|
||||
lastUpdate.setTimeZone(PACIFIC_TIME);
|
||||
|
||||
// Update every day
|
||||
if (now.get(Calendar.DAY_OF_YEAR) != lastUpdate
|
||||
.get(Calendar.DAY_OF_YEAR)
|
||||
|| now.get(Calendar.YEAR) != lastUpdate.get(Calendar.YEAR)) {
|
||||
GetRouteFareTask fareTask = new GetRouteFareTask() {
|
||||
@Override
|
||||
public void onResult(String fare) {
|
||||
stationPair.setFare(fare);
|
||||
stationPair.setFareLastUpdated(System
|
||||
.currentTimeMillis());
|
||||
getListAdapter().notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Exception exception) {
|
||||
// Ignore... we can do this later
|
||||
}
|
||||
};
|
||||
fareTask.execute(new GetRouteFareTask.Params(stationPair
|
||||
.getOrigin(), stationPair.getDestination()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putBoolean("hasActionMode", mActionMode != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
Ticker.getInstance().startTicking(this);
|
||||
startEtdListeners();
|
||||
}
|
||||
|
||||
private void startEtdListeners() {
|
||||
if (mRoutesAdapter != null && !mRoutesAdapter.isEmpty()
|
||||
&& !mRoutesAdapter.areEtdListenersActive()) {
|
||||
mRoutesAdapter.setUpEtdListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
if (mRoutesAdapter != null && mRoutesAdapter.areEtdListenersActive()) {
|
||||
mRoutesAdapter.clearEtdListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
Ticker.getInstance().stopTicking(this);
|
||||
app.saveFavorites();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mRoutesAdapter != null) {
|
||||
mRoutesAdapter.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
if (hasFocus) {
|
||||
Ticker.getInstance().startTicking(this);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getSupportMenuInflater();
|
||||
inflater.inflate(R.menu.routes_list_menu, menu);
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
private MenuItem elevatorMenuItem;
|
||||
private View origElevatorActionView;
|
||||
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int itemId = item.getItemId();
|
||||
if (itemId == R.id.add_favorite_menu_button) {
|
||||
new AddRouteDialogFragment().show(getSupportFragmentManager()
|
||||
.beginTransaction());
|
||||
return true;
|
||||
} else if (itemId == R.id.view_system_map_button) {
|
||||
startActivity(new Intent(this, ViewMapActivity.class));
|
||||
return true;
|
||||
} else if (itemId == R.id.elevator_button) {
|
||||
elevatorMenuItem = item;
|
||||
fetchElevatorInfo();
|
||||
origElevatorActionView = elevatorMenuItem.getActionView();
|
||||
elevatorMenuItem.setActionView(R.layout.progress_spinner);
|
||||
return true;
|
||||
} else {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Background
|
||||
void fetchAlerts() {
|
||||
Log.d(TAG, "Fetching alerts");
|
||||
AlertList alertList = alertsClient.getAlerts();
|
||||
if (alertList.hasAlerts()) {
|
||||
StringBuilder alertText = new StringBuilder();
|
||||
boolean firstAlert = true;
|
||||
for (Alert alert : alertList.getAlerts()) {
|
||||
if (!firstAlert) {
|
||||
alertText.append("\n\n");
|
||||
}
|
||||
alertText.append(alert.getPostedTime()).append("\n");
|
||||
alertText.append(alert.getDescription());
|
||||
firstAlert = false;
|
||||
}
|
||||
showAlertMessage(alertText.toString());
|
||||
} else if (alertList.areNoDelaysReported()) {
|
||||
showAlertMessage(NO_DELAYS_REPORTED);
|
||||
} else {
|
||||
hideAlertMessage();
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
void hideAlertMessage() {
|
||||
mCurrentAlerts = null;
|
||||
alertMessages.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
void showAlertMessage(String messageText) {
|
||||
if (messageText == null) {
|
||||
hideAlertMessage();
|
||||
return;
|
||||
} else if (messageText == NO_DELAYS_REPORTED) {
|
||||
alertMessages.setCompoundDrawablesWithIntrinsicBounds(
|
||||
R.drawable.ic_allgood, 0, 0, 0);
|
||||
} else {
|
||||
alertMessages.setCompoundDrawablesWithIntrinsicBounds(
|
||||
R.drawable.ic_warn, 0, 0, 0);
|
||||
}
|
||||
mCurrentAlerts = messageText;
|
||||
alertMessages.setText(messageText);
|
||||
alertMessages.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Background
|
||||
void fetchElevatorInfo() {
|
||||
String elevatorMessage = elevatorClient.getElevatorMessage();
|
||||
if (elevatorMessage != null) {
|
||||
showElevatorMessage(elevatorMessage);
|
||||
}
|
||||
resetElevatorMenuGraphic();
|
||||
}
|
||||
|
||||
@UiThread
|
||||
void resetElevatorMenuGraphic() {
|
||||
ActivityCompat.invalidateOptionsMenu(this);
|
||||
elevatorMenuItem.setActionView(origElevatorActionView);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
void showElevatorMessage(String message) {
|
||||
Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setMessage(message);
|
||||
builder.setTitle("Elevator status");
|
||||
builder.show();
|
||||
}
|
||||
|
||||
private void startContextualActionMode() {
|
||||
mActionMode = startActionMode(new RouteActionMode());
|
||||
mActionMode.setTitle(mCurrentlySelectedStationPair.getOrigin().name);
|
||||
mActionMode.setSubtitle("to "
|
||||
+ mCurrentlySelectedStationPair.getDestination().name);
|
||||
}
|
||||
|
||||
private final class RouteActionMode implements ActionMode.Callback {
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
mode.getMenuInflater().inflate(R.menu.route_context_menu, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
||||
if (item.getItemId() == R.id.view) {
|
||||
Intent intent = new Intent(RoutesListActivity.this,
|
||||
ViewDeparturesActivity.class);
|
||||
intent.putExtra(Constants.STATION_PAIR_EXTRA,
|
||||
mCurrentlySelectedStationPair);
|
||||
startActivity(intent);
|
||||
mode.finish();
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.delete) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(
|
||||
RoutesListActivity.this);
|
||||
builder.setCancelable(false);
|
||||
builder.setMessage("Are you sure you want to delete this route?");
|
||||
builder.setPositiveButton(R.string.yes,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
getListAdapter().remove(
|
||||
mCurrentlySelectedStationPair);
|
||||
mCurrentlySelectedStationPair = null;
|
||||
mActionMode.finish();
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
dialog.cancel();
|
||||
}
|
||||
});
|
||||
builder.show();
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyActionMode(ActionMode mode) {
|
||||
mActionMode = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTickInterval() {
|
||||
return 90;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick(long mTickCount) {
|
||||
fetchAlerts();
|
||||
}
|
||||
}
|
@ -20,99 +20,99 @@ import com.dougkeen.bart.model.Departure;
|
||||
|
||||
public class TrainAlarmDialogFragment extends DialogFragment {
|
||||
|
||||
private static final String KEY_LAST_ALARM_LEAD_TIME = "lastAlarmLeadTime";
|
||||
private static final String KEY_LAST_ALARM_LEAD_TIME = "lastAlarmLeadTime";
|
||||
|
||||
public TrainAlarmDialogFragment() {
|
||||
super();
|
||||
}
|
||||
public TrainAlarmDialogFragment() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setShowsDialog(true);
|
||||
}
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setShowsDialog(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
setUpNumberPickerValues(getDialog());
|
||||
}
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
setUpNumberPickerValues(getDialog());
|
||||
}
|
||||
|
||||
private void setUpNumberPickerValues(Dialog dialog) {
|
||||
SharedPreferences preferences = getActivity().getPreferences(
|
||||
Context.MODE_PRIVATE);
|
||||
int lastAlarmLeadTime = preferences.getInt(KEY_LAST_ALARM_LEAD_TIME, 5);
|
||||
private void setUpNumberPickerValues(Dialog dialog) {
|
||||
SharedPreferences preferences = getActivity().getPreferences(
|
||||
Context.MODE_PRIVATE);
|
||||
int lastAlarmLeadTime = preferences.getInt(KEY_LAST_ALARM_LEAD_TIME, 5);
|
||||
|
||||
NumberPicker numberPicker = (NumberPicker) dialog
|
||||
.findViewById(R.id.numberPicker);
|
||||
NumberPicker numberPicker = (NumberPicker) dialog
|
||||
.findViewById(R.id.numberPicker);
|
||||
|
||||
BartRunnerApplication application = (BartRunnerApplication) getActivity()
|
||||
.getApplication();
|
||||
BartRunnerApplication application = (BartRunnerApplication) getActivity()
|
||||
.getApplication();
|
||||
|
||||
final Departure boardedDeparture = application.getBoardedDeparture();
|
||||
final int maxValue = boardedDeparture.getMeanSecondsLeft() / 60;
|
||||
final Departure boardedDeparture = application.getBoardedDeparture();
|
||||
final int maxValue = boardedDeparture.getMeanSecondsLeft() / 60;
|
||||
|
||||
String[] displayedValues = new String[maxValue];
|
||||
for (int i = 1; i <= maxValue; i++) {
|
||||
displayedValues[i - 1] = String.valueOf(i);
|
||||
}
|
||||
numberPicker.setMinValue(1);
|
||||
numberPicker.setMaxValue(maxValue);
|
||||
numberPicker.setDisplayedValues(displayedValues);
|
||||
String[] displayedValues = new String[maxValue];
|
||||
for (int i = 1; i <= maxValue; i++) {
|
||||
displayedValues[i - 1] = String.valueOf(i);
|
||||
}
|
||||
numberPicker.setMinValue(1);
|
||||
numberPicker.setMaxValue(maxValue);
|
||||
numberPicker.setDisplayedValues(displayedValues);
|
||||
|
||||
if (boardedDeparture.isAlarmPending()) {
|
||||
numberPicker.setValue(boardedDeparture.getAlarmLeadTimeMinutes());
|
||||
} else if (maxValue >= lastAlarmLeadTime) {
|
||||
numberPicker.setValue(lastAlarmLeadTime);
|
||||
} else if (maxValue >= 5) {
|
||||
numberPicker.setValue(5);
|
||||
} else if (maxValue >= 3) {
|
||||
numberPicker.setValue(3);
|
||||
} else {
|
||||
numberPicker.setValue(1);
|
||||
}
|
||||
}
|
||||
if (boardedDeparture.isAlarmPending()) {
|
||||
numberPicker.setValue(boardedDeparture.getAlarmLeadTimeMinutes());
|
||||
} else if (maxValue >= lastAlarmLeadTime) {
|
||||
numberPicker.setValue(lastAlarmLeadTime);
|
||||
} else if (maxValue >= 5) {
|
||||
numberPicker.setValue(5);
|
||||
} else if (maxValue >= 3) {
|
||||
numberPicker.setValue(3);
|
||||
} else {
|
||||
numberPicker.setValue(1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final FragmentActivity activity = getActivity();
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final FragmentActivity activity = getActivity();
|
||||
|
||||
final View dialogView = LayoutInflater.inflate(activity,
|
||||
R.layout.train_alarm_dialog);
|
||||
final View dialogView = LayoutInflater.inflate(activity,
|
||||
R.layout.train_alarm_dialog);
|
||||
|
||||
return new AlertDialog.Builder(activity)
|
||||
.setTitle(R.string.set_up_departure_alarm)
|
||||
.setCancelable(true)
|
||||
.setView(dialogView)
|
||||
.setPositiveButton(R.string.ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
NumberPicker numberPicker = (NumberPicker) getDialog()
|
||||
.findViewById(R.id.numberPicker);
|
||||
final int alarmLeadTime = numberPicker
|
||||
.getValue();
|
||||
return new AlertDialog.Builder(activity)
|
||||
.setTitle(R.string.set_up_departure_alarm)
|
||||
.setCancelable(true)
|
||||
.setView(dialogView)
|
||||
.setPositiveButton(R.string.ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
NumberPicker numberPicker = (NumberPicker) getDialog()
|
||||
.findViewById(R.id.numberPicker);
|
||||
final int alarmLeadTime = numberPicker
|
||||
.getValue();
|
||||
|
||||
// Save most recent selection
|
||||
Editor editor = getActivity().getPreferences(
|
||||
Context.MODE_PRIVATE).edit();
|
||||
editor.putInt(KEY_LAST_ALARM_LEAD_TIME,
|
||||
alarmLeadTime);
|
||||
editor.commit();
|
||||
// Save most recent selection
|
||||
Editor editor = getActivity().getPreferences(
|
||||
Context.MODE_PRIVATE).edit();
|
||||
editor.putInt(KEY_LAST_ALARM_LEAD_TIME,
|
||||
alarmLeadTime);
|
||||
editor.commit();
|
||||
|
||||
((BartRunnerApplication) getActivity()
|
||||
.getApplication())
|
||||
.getBoardedDeparture().setUpAlarm(
|
||||
alarmLeadTime);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog,
|
||||
int whichButton) {
|
||||
dialog.cancel();
|
||||
}
|
||||
}).create();
|
||||
}
|
||||
((BartRunnerApplication) getActivity()
|
||||
.getApplication())
|
||||
.getBoardedDeparture().setUpAlarm(
|
||||
alarmLeadTime);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog,
|
||||
int whichButton) {
|
||||
dialog.cancel();
|
||||
}
|
||||
}).create();
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -12,36 +12,36 @@ import com.dougkeen.bart.R;
|
||||
|
||||
public class ViewMapActivity extends Activity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
WebView webview = new WebView(this);
|
||||
setContentView(webview);
|
||||
WebView webview = new WebView(this);
|
||||
setContentView(webview);
|
||||
|
||||
webview.getSettings().setBuiltInZoomControls(true);
|
||||
webview.getSettings().setSupportZoom(true);
|
||||
webview.getSettings().setBuiltInZoomControls(true);
|
||||
webview.getSettings().setSupportZoom(true);
|
||||
|
||||
webview.loadUrl("file:///android_res/drawable/map.png");
|
||||
webview.loadUrl("file:///android_res/drawable/map.png");
|
||||
|
||||
getSupportActionBar().setHomeButtonEnabled(true);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
getSupportActionBar().setHomeButtonEnabled(true);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getSupportMenuInflater();
|
||||
inflater.inflate(R.menu.system_map_menu, menu);
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getSupportMenuInflater();
|
||||
inflater.inflate(R.menu.system_map_menu, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,51 +7,51 @@ import android.widget.TextView;
|
||||
import com.dougkeen.bart.model.TextProvider;
|
||||
|
||||
public class CountdownTextView extends TextView implements
|
||||
Ticker.TickSubscriber {
|
||||
Ticker.TickSubscriber {
|
||||
|
||||
private TextProvider mTextProvider;
|
||||
private int mTickInterval;
|
||||
private TextProvider mTextProvider;
|
||||
private int mTickInterval;
|
||||
|
||||
public CountdownTextView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public CountdownTextView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public CountdownTextView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
setInstanceVarsFromAttrs(attrs);
|
||||
}
|
||||
public CountdownTextView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
setInstanceVarsFromAttrs(attrs);
|
||||
}
|
||||
|
||||
public CountdownTextView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setInstanceVarsFromAttrs(attrs);
|
||||
}
|
||||
public CountdownTextView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setInstanceVarsFromAttrs(attrs);
|
||||
}
|
||||
|
||||
private void setInstanceVarsFromAttrs(AttributeSet attrs) {
|
||||
int tickInterval = attrs.getAttributeIntValue(
|
||||
"http://schemas.android.com/apk/res/com.dougkeen.bart",
|
||||
"tickInterval", 0);
|
||||
if (tickInterval > 0) {
|
||||
setTickInterval(tickInterval);
|
||||
}
|
||||
}
|
||||
private void setInstanceVarsFromAttrs(AttributeSet attrs) {
|
||||
int tickInterval = attrs.getAttributeIntValue(
|
||||
"http://schemas.android.com/apk/res/com.dougkeen.bart",
|
||||
"tickInterval", 0);
|
||||
if (tickInterval > 0) {
|
||||
setTickInterval(tickInterval);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTextProvider(TextProvider provider) {
|
||||
mTextProvider = provider;
|
||||
Ticker.getInstance().addSubscriber(this, getContext());
|
||||
}
|
||||
public void setTextProvider(TextProvider provider) {
|
||||
mTextProvider = provider;
|
||||
Ticker.getInstance().addSubscriber(this, getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTickInterval() {
|
||||
return mTickInterval;
|
||||
}
|
||||
@Override
|
||||
public int getTickInterval() {
|
||||
return mTickInterval;
|
||||
}
|
||||
|
||||
public void setTickInterval(int tickInterval) {
|
||||
this.mTickInterval = tickInterval;
|
||||
}
|
||||
public void setTickInterval(int tickInterval) {
|
||||
this.mTickInterval = tickInterval;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick(long tickNumber) {
|
||||
setText(mTextProvider.getText(tickNumber));
|
||||
}
|
||||
@Override
|
||||
public void onTick(long tickNumber) {
|
||||
setText(mTextProvider.getText(tickNumber));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,35 +8,35 @@ import android.widget.RelativeLayout;
|
||||
import com.dougkeen.bart.R;
|
||||
|
||||
public class DepartureListItemLayout extends RelativeLayout implements
|
||||
Checkable {
|
||||
Checkable {
|
||||
|
||||
public DepartureListItemLayout(Context context) {
|
||||
super(context);
|
||||
LayoutInflater.from(context).inflate(R.layout.departure_listing, this,
|
||||
true);
|
||||
}
|
||||
public DepartureListItemLayout(Context context) {
|
||||
super(context);
|
||||
LayoutInflater.from(context).inflate(R.layout.departure_listing, this,
|
||||
true);
|
||||
}
|
||||
|
||||
private boolean mChecked;
|
||||
private boolean mChecked;
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return mChecked;
|
||||
}
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return mChecked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChecked(boolean checked) {
|
||||
mChecked = checked;
|
||||
if (isChecked()) {
|
||||
setBackgroundDrawable(getContext().getResources().getDrawable(
|
||||
R.color.blue_selection));
|
||||
} else {
|
||||
setBackgroundDrawable(getContext().getResources().getDrawable(
|
||||
android.R.color.transparent));
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void setChecked(boolean checked) {
|
||||
mChecked = checked;
|
||||
if (isChecked()) {
|
||||
setBackgroundDrawable(getContext().getResources().getDrawable(
|
||||
R.color.blue_selection));
|
||||
} else {
|
||||
setBackgroundDrawable(getContext().getResources().getDrawable(
|
||||
android.R.color.transparent));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggle() {
|
||||
setChecked(!isChecked());
|
||||
}
|
||||
@Override
|
||||
public void toggle() {
|
||||
setChecked(!isChecked());
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ 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.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.VelocityTracker;
|
||||
@ -40,7 +41,7 @@ import com.nineoldandroids.animation.ValueAnimator;
|
||||
* callback). Also, a {@link android.view.View.OnTouchListener} that makes any
|
||||
* {@link View} dismissable when the user swipes (drags her finger) horizontally
|
||||
* across the view.
|
||||
*
|
||||
* <p>
|
||||
* <p>
|
||||
* <em>For {@link android.widget.ListView} list items that don't manage their own touch events
|
||||
* (i.e. you're using
|
||||
@ -48,11 +49,11 @@ import com.nineoldandroids.animation.ValueAnimator;
|
||||
* or an equivalent listener on {@link android.app.ListActivity} or
|
||||
* {@link android.app.ListFragment}, use {@link SwipeDismissListViewTouchListener} instead.</em>
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* <p>
|
||||
* Example usage:
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* <pre>
|
||||
* view.setOnTouchListener(new SwipeDismisser(view, null, // Optional
|
||||
* // token/cookie
|
||||
@ -60,256 +61,251 @@ import com.nineoldandroids.animation.ValueAnimator;
|
||||
* new SwipeDismisser.OnDismissCallback() {
|
||||
* public void onDismiss(View view, Object token) {
|
||||
* parent.removeView(view);
|
||||
* }
|
||||
* }));
|
||||
* }
|
||||
* }));
|
||||
* </pre>
|
||||
*
|
||||
* @see SwipeDismissListViewTouchListener
|
||||
*/
|
||||
public class SwipeHelper implements View.OnTouchListener {
|
||||
// Cached ViewConfiguration and system-wide constant values
|
||||
private int mSlop;
|
||||
private int mMinFlingVelocity;
|
||||
private int mMaxFlingVelocity;
|
||||
private long mAnimationTime;
|
||||
// Cached ViewConfiguration and system-wide constant values
|
||||
private int mSlop;
|
||||
private int mMinFlingVelocity;
|
||||
private int mMaxFlingVelocity;
|
||||
private long mAnimationTime;
|
||||
|
||||
// Fixed properties
|
||||
private View mView;
|
||||
private OnDismissCallback mCallback;
|
||||
private int mViewWidth = 1; // 1 and not 0 to prevent dividing by zero
|
||||
// Fixed properties
|
||||
private View mView;
|
||||
private OnDismissCallback mCallback;
|
||||
private int mViewWidth = 1; // 1 and not 0 to prevent dividing by zero
|
||||
|
||||
// Transient properties
|
||||
private float mDownX;
|
||||
private boolean mSwiping;
|
||||
private Object mToken;
|
||||
private VelocityTracker mVelocityTracker;
|
||||
private float mTranslationX;
|
||||
// Transient properties
|
||||
private float mDownX;
|
||||
private boolean mSwiping;
|
||||
private Object mToken;
|
||||
private VelocityTracker mVelocityTracker;
|
||||
private float mTranslationX;
|
||||
|
||||
/**
|
||||
* The callback interface used by {@link SwipeHelper} to inform its client
|
||||
* about a successful dismissal of the view for which it was created.
|
||||
*/
|
||||
public interface OnDismissCallback {
|
||||
/**
|
||||
* Called when the user has indicated they she would like to dismiss the
|
||||
* view.
|
||||
*
|
||||
* @param view
|
||||
* The originating {@link View} to be dismissed.
|
||||
* @param token
|
||||
* The optional token passed to this object's constructor.
|
||||
*/
|
||||
void onDismiss(View view, Object token);
|
||||
}
|
||||
/**
|
||||
* The callback interface used by {@link SwipeHelper} to inform its client
|
||||
* about a successful dismissal of the view for which it was created.
|
||||
*/
|
||||
public interface OnDismissCallback {
|
||||
/**
|
||||
* Called when the user has indicated they she would like to dismiss the
|
||||
* view.
|
||||
*
|
||||
* @param view The originating {@link View} to be dismissed.
|
||||
* @param token The optional token passed to this object's constructor.
|
||||
*/
|
||||
void onDismiss(View view, Object token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new swipe-to-dismiss touch listener for the given view.
|
||||
*
|
||||
* @param view
|
||||
* The view to make dismissable.
|
||||
* @param token
|
||||
* An optional token/cookie object to be passed through to the
|
||||
* callback.
|
||||
* @param callback
|
||||
* The callback to trigger when the user has indicated that she
|
||||
* would like to dismiss this view.
|
||||
*/
|
||||
public SwipeHelper(View view, Object token, OnDismissCallback callback) {
|
||||
ViewConfiguration vc = ViewConfiguration.get(view.getContext());
|
||||
mSlop = vc.getScaledTouchSlop();
|
||||
mMinFlingVelocity = vc.getScaledMinimumFlingVelocity();
|
||||
mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity();
|
||||
mAnimationTime = view.getContext().getResources()
|
||||
.getInteger(android.R.integer.config_shortAnimTime);
|
||||
mView = view;
|
||||
mToken = token;
|
||||
mCallback = callback;
|
||||
}
|
||||
/**
|
||||
* Constructs a new swipe-to-dismiss touch listener for the given view.
|
||||
*
|
||||
* @param view The view to make dismissable.
|
||||
* @param token An optional token/cookie object to be passed through to the
|
||||
* callback.
|
||||
* @param callback The callback to trigger when the user has indicated that she
|
||||
* would like to dismiss this view.
|
||||
*/
|
||||
public SwipeHelper(View view, Object token, OnDismissCallback callback) {
|
||||
ViewConfiguration vc = ViewConfiguration.get(view.getContext());
|
||||
mSlop = vc.getScaledTouchSlop();
|
||||
mMinFlingVelocity = vc.getScaledMinimumFlingVelocity();
|
||||
mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity();
|
||||
mAnimationTime = view.getContext().getResources()
|
||||
.getInteger(android.R.integer.config_shortAnimTime);
|
||||
mView = view;
|
||||
mToken = token;
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View view, MotionEvent motionEvent) {
|
||||
Log.v(Constants.TAG, "onTouch()");
|
||||
// offset because the view is translated during swipe
|
||||
motionEvent.offsetLocation(mTranslationX, 0);
|
||||
@Override
|
||||
public boolean onTouch(View view, MotionEvent motionEvent) {
|
||||
Log.v(Constants.TAG, "onTouch()");
|
||||
// offset because the view is translated during swipe
|
||||
motionEvent.offsetLocation(mTranslationX, 0);
|
||||
|
||||
if (mViewWidth < 2) {
|
||||
mViewWidth = mView.getWidth();
|
||||
}
|
||||
if (mViewWidth < 2) {
|
||||
mViewWidth = mView.getWidth();
|
||||
}
|
||||
|
||||
switch (motionEvent.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN: {
|
||||
// TODO: ensure this is a finger, and set a flag
|
||||
mDownX = motionEvent.getRawX();
|
||||
mVelocityTracker = VelocityTracker.obtain();
|
||||
mVelocityTracker.addMovement(motionEvent);
|
||||
view.onTouchEvent(motionEvent);
|
||||
return false;
|
||||
}
|
||||
switch (motionEvent.getActionMasked()) {
|
||||
case MotionEvent.ACTION_DOWN: {
|
||||
// TODO: ensure this is a finger, and set a flag
|
||||
mDownX = motionEvent.getRawX();
|
||||
mVelocityTracker = VelocityTracker.obtain();
|
||||
mVelocityTracker.addMovement(motionEvent);
|
||||
view.onTouchEvent(motionEvent);
|
||||
return false;
|
||||
}
|
||||
|
||||
case MotionEvent.ACTION_UP: {
|
||||
if (mVelocityTracker == null) {
|
||||
break;
|
||||
}
|
||||
case MotionEvent.ACTION_UP: {
|
||||
if (mVelocityTracker == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
float deltaX = motionEvent.getRawX() - mDownX;
|
||||
mVelocityTracker.addMovement(motionEvent);
|
||||
mVelocityTracker.computeCurrentVelocity(1000);
|
||||
float velocityX = Math.abs(mVelocityTracker.getXVelocity());
|
||||
float velocityY = Math.abs(mVelocityTracker.getYVelocity());
|
||||
boolean dismiss = false;
|
||||
boolean dismissRight = false;
|
||||
if (Math.abs(deltaX) > mViewWidth / 2) {
|
||||
dismiss = true;
|
||||
dismissRight = deltaX > 0;
|
||||
} else if (mMinFlingVelocity <= velocityX
|
||||
&& velocityX <= mMaxFlingVelocity && velocityY < velocityX) {
|
||||
dismiss = true;
|
||||
dismissRight = mVelocityTracker.getXVelocity() > 0;
|
||||
}
|
||||
if (dismiss) {
|
||||
// dismiss
|
||||
dismissWithAnimation(dismissRight);
|
||||
} else {
|
||||
// cancel
|
||||
animate(mView).translationX(0).alpha(1)
|
||||
.setDuration(mAnimationTime).setListener(null);
|
||||
}
|
||||
mVelocityTracker = null;
|
||||
mTranslationX = 0;
|
||||
mDownX = 0;
|
||||
mSwiping = false;
|
||||
break;
|
||||
}
|
||||
float deltaX = motionEvent.getRawX() - mDownX;
|
||||
mVelocityTracker.addMovement(motionEvent);
|
||||
mVelocityTracker.computeCurrentVelocity(1000);
|
||||
float velocityX = Math.abs(mVelocityTracker.getXVelocity());
|
||||
float velocityY = Math.abs(mVelocityTracker.getYVelocity());
|
||||
boolean dismiss = false;
|
||||
boolean dismissRight = false;
|
||||
if (Math.abs(deltaX) > mViewWidth / 2) {
|
||||
dismiss = true;
|
||||
dismissRight = deltaX > 0;
|
||||
} else if (mMinFlingVelocity <= velocityX
|
||||
&& velocityX <= mMaxFlingVelocity && velocityY < velocityX) {
|
||||
dismiss = true;
|
||||
dismissRight = mVelocityTracker.getXVelocity() > 0;
|
||||
}
|
||||
if (dismiss) {
|
||||
// dismiss
|
||||
dismissWithAnimation(dismissRight);
|
||||
} else {
|
||||
// cancel
|
||||
animate(mView).translationX(0).alpha(1)
|
||||
.setDuration(mAnimationTime).setListener(null);
|
||||
}
|
||||
mVelocityTracker = null;
|
||||
mTranslationX = 0;
|
||||
mDownX = 0;
|
||||
mSwiping = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case MotionEvent.ACTION_MOVE: {
|
||||
if (mVelocityTracker == null) {
|
||||
break;
|
||||
}
|
||||
case MotionEvent.ACTION_MOVE: {
|
||||
if (mVelocityTracker == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
mVelocityTracker.addMovement(motionEvent);
|
||||
float deltaX = motionEvent.getRawX() - mDownX;
|
||||
if (Math.abs(deltaX) > mSlop) {
|
||||
mSwiping = true;
|
||||
mView.getParent().requestDisallowInterceptTouchEvent(true);
|
||||
mVelocityTracker.addMovement(motionEvent);
|
||||
float deltaX = motionEvent.getRawX() - mDownX;
|
||||
if (Math.abs(deltaX) > mSlop) {
|
||||
mSwiping = true;
|
||||
mView.getParent().requestDisallowInterceptTouchEvent(true);
|
||||
|
||||
// Cancel listview's touch
|
||||
MotionEvent cancelEvent = MotionEvent.obtain(motionEvent);
|
||||
cancelEvent
|
||||
.setAction(MotionEvent.ACTION_CANCEL
|
||||
| (motionEvent.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
|
||||
mView.onTouchEvent(cancelEvent);
|
||||
}
|
||||
// Cancel listview's touch
|
||||
MotionEvent cancelEvent = MotionEvent.obtain(motionEvent);
|
||||
cancelEvent
|
||||
.setAction(MotionEvent.ACTION_CANCEL
|
||||
| (motionEvent.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
|
||||
mView.onTouchEvent(cancelEvent);
|
||||
}
|
||||
|
||||
if (mSwiping) {
|
||||
mTranslationX = deltaX;
|
||||
setTranslationX(mView, deltaX);
|
||||
// TODO: use an ease-out interpolator or such
|
||||
setAlpha(
|
||||
mView,
|
||||
Math.max(
|
||||
0f,
|
||||
Math.min(1f, 1f - 2f * Math.abs(deltaX)
|
||||
/ mViewWidth)));
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (mSwiping) {
|
||||
mTranslationX = deltaX;
|
||||
setTranslationX(mView, deltaX);
|
||||
// TODO: use an ease-out interpolator or such
|
||||
setAlpha(
|
||||
mView,
|
||||
Math.max(
|
||||
0f,
|
||||
Math.min(1f, 1f - 2f * Math.abs(deltaX)
|
||||
/ mViewWidth)));
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void dismissWithAnimation(boolean dismissRight) {
|
||||
animate(mView).translationX(dismissRight ? mViewWidth : -mViewWidth)
|
||||
.alpha(0).setDuration(mAnimationTime)
|
||||
.setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
performDismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
public void dismissWithAnimation(boolean dismissRight) {
|
||||
animate(mView).translationX(dismissRight ? mViewWidth : -mViewWidth)
|
||||
.alpha(0).setDuration(mAnimationTime)
|
||||
.setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
performDismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void performDismiss() {
|
||||
// Animate the dismissed view to zero-height and then fire the dismiss
|
||||
// callback.
|
||||
// This triggers layout on each animation frame; in the future we may
|
||||
// want to do something
|
||||
// smarter and more performant.
|
||||
private void performDismiss() {
|
||||
// Animate the dismissed view to zero-height and then fire the dismiss
|
||||
// callback.
|
||||
// This triggers layout on each animation frame; in the future we may
|
||||
// want to do something
|
||||
// smarter and more performant.
|
||||
|
||||
final ViewGroup.LayoutParams lp = mView.getLayoutParams();
|
||||
final int originalHeight = mView.getHeight();
|
||||
final ViewGroup.LayoutParams lp = mView.getLayoutParams();
|
||||
final int originalHeight = mView.getHeight();
|
||||
|
||||
ValueAnimator animator = ValueAnimator.ofInt(originalHeight, 1)
|
||||
.setDuration(mAnimationTime);
|
||||
ValueAnimator animator = ValueAnimator.ofInt(originalHeight, 1)
|
||||
.setDuration(mAnimationTime);
|
||||
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mCallback.onDismiss(mView, mToken);
|
||||
// Reset view presentation
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mCallback.onDismiss(mView, mToken);
|
||||
// Reset view presentation
|
||||
|
||||
/*
|
||||
* Alpha stays at 0, otherwise Android 2.x leaves weird
|
||||
* Alpha stays at 0, otherwise Android 2.x leaves weird
|
||||
* artifacts
|
||||
*/
|
||||
// setAlpha(mView, 1f);
|
||||
// setAlpha(mView, 1f);
|
||||
|
||||
setTranslationX(mView, 0);
|
||||
lp.height = originalHeight;
|
||||
mView.setLayoutParams(lp);
|
||||
}
|
||||
});
|
||||
setTranslationX(mView, 0);
|
||||
lp.height = originalHeight;
|
||||
mView.setLayoutParams(lp);
|
||||
}
|
||||
});
|
||||
|
||||
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator valueAnimator) {
|
||||
lp.height = (Integer) valueAnimator.getAnimatedValue();
|
||||
mView.setLayoutParams(lp);
|
||||
}
|
||||
});
|
||||
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator valueAnimator) {
|
||||
lp.height = (Integer) valueAnimator.getAnimatedValue();
|
||||
mView.setLayoutParams(lp);
|
||||
}
|
||||
});
|
||||
|
||||
animator.start();
|
||||
}
|
||||
animator.start();
|
||||
}
|
||||
|
||||
public void showWithAnimation() {
|
||||
final int measureSpec = MeasureSpec.makeMeasureSpec(
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY);
|
||||
mView.measure(measureSpec, measureSpec);
|
||||
mViewWidth = mView.getMeasuredWidth();
|
||||
final int viewHeight = mView.getMeasuredHeight();
|
||||
setAlpha(mView, 0f);
|
||||
public void showWithAnimation() {
|
||||
final int measureSpec = MeasureSpec.makeMeasureSpec(
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY);
|
||||
mView.measure(measureSpec, measureSpec);
|
||||
mViewWidth = mView.getMeasuredWidth();
|
||||
final int viewHeight = mView.getMeasuredHeight();
|
||||
setAlpha(mView, 0f);
|
||||
|
||||
final ViewGroup.LayoutParams lp = mView.getLayoutParams();
|
||||
lp.width = mViewWidth;
|
||||
final ViewGroup.LayoutParams lp = mView.getLayoutParams();
|
||||
lp.width = mViewWidth;
|
||||
|
||||
setTranslationX(mView, mViewWidth);
|
||||
setTranslationX(mView, mViewWidth);
|
||||
|
||||
// Grow space
|
||||
ValueAnimator animator = ValueAnimator.ofInt(1, viewHeight)
|
||||
.setDuration(mAnimationTime);
|
||||
// Grow space
|
||||
ValueAnimator animator = ValueAnimator.ofInt(1, viewHeight)
|
||||
.setDuration(mAnimationTime);
|
||||
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
// Reset view presentation
|
||||
// mView.requestLayout();
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
// Reset view presentation
|
||||
// mView.requestLayout();
|
||||
|
||||
// Swipe view into space that opened up
|
||||
animate(mView).translationX(0).alpha(1)
|
||||
.setDuration(mAnimationTime)
|
||||
.setListener(new AnimatorListenerAdapter() {
|
||||
});
|
||||
}
|
||||
});
|
||||
// Swipe view into space that opened up
|
||||
animate(mView).translationX(0).alpha(1)
|
||||
.setDuration(mAnimationTime)
|
||||
.setListener(new AnimatorListenerAdapter() {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator valueAnimator) {
|
||||
lp.height = (Integer) valueAnimator.getAnimatedValue();
|
||||
mView.setLayoutParams(lp);
|
||||
}
|
||||
});
|
||||
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator valueAnimator) {
|
||||
lp.height = (Integer) valueAnimator.getAnimatedValue();
|
||||
mView.setLayoutParams(lp);
|
||||
}
|
||||
});
|
||||
|
||||
animator.start();
|
||||
}
|
||||
animator.start();
|
||||
}
|
||||
}
|
@ -7,108 +7,108 @@ import android.content.Context;
|
||||
import android.os.Handler;
|
||||
|
||||
public class Ticker {
|
||||
public static interface TickSubscriber {
|
||||
int getTickInterval();
|
||||
public interface TickSubscriber {
|
||||
int getTickInterval();
|
||||
|
||||
void onTick(long mTickCount);
|
||||
}
|
||||
void onTick(long mTickCount);
|
||||
}
|
||||
|
||||
private static Ticker sInstance;
|
||||
private static Ticker sInstance;
|
||||
|
||||
private WeakHashMap<TickSubscriber, Object> mSubscribers;
|
||||
private WeakHashMap<TickSubscriber, Object> mSubscribers;
|
||||
|
||||
private WeakHashMap<Context, Object> mTickerHosts;
|
||||
private WeakHashMap<Context, Object> mTickerHosts;
|
||||
|
||||
private TickerEngine mEngine;
|
||||
private TickerEngine mEngine;
|
||||
|
||||
private static class TickerEngine implements Runnable {
|
||||
private static class TickerEngine implements Runnable {
|
||||
|
||||
private static final int TICK_INTERVAL_MILLIS = 1000;
|
||||
private Ticker publisher;
|
||||
private Handler mHandler;
|
||||
private boolean mPendingRequest = false;
|
||||
private boolean mForceStop = false;
|
||||
private long mTickCount = 0;
|
||||
private static final int TICK_INTERVAL_MILLIS = 1000;
|
||||
private Ticker publisher;
|
||||
private Handler mHandler;
|
||||
private boolean mPendingRequest = false;
|
||||
private boolean mForceStop = false;
|
||||
private long mTickCount = 0;
|
||||
|
||||
public TickerEngine(Ticker publisher) {
|
||||
this.publisher = publisher;
|
||||
this.mHandler = new Handler();
|
||||
}
|
||||
public TickerEngine(Ticker publisher) {
|
||||
this.publisher = publisher;
|
||||
this.mHandler = new Handler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
mPendingRequest = false;
|
||||
if (mForceStop) {
|
||||
mForceStop = false;
|
||||
return;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
mPendingRequest = false;
|
||||
if (mForceStop) {
|
||||
mForceStop = false;
|
||||
return;
|
||||
}
|
||||
|
||||
long startTimeNanos = System.nanoTime();
|
||||
Iterator<TickSubscriber> iterator = publisher.mSubscribers.keySet()
|
||||
.iterator();
|
||||
boolean stillHasListeners = false;
|
||||
while (iterator.hasNext()) {
|
||||
TickSubscriber subscriber = iterator.next();
|
||||
if (subscriber == null) {
|
||||
continue;
|
||||
}
|
||||
long startTimeNanos = System.nanoTime();
|
||||
Iterator<TickSubscriber> iterator = publisher.mSubscribers.keySet()
|
||||
.iterator();
|
||||
boolean stillHasListeners = false;
|
||||
while (iterator.hasNext()) {
|
||||
TickSubscriber subscriber = iterator.next();
|
||||
if (subscriber == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
stillHasListeners = true;
|
||||
if (subscriber.getTickInterval() > 0
|
||||
&& mTickCount % subscriber.getTickInterval() == 0)
|
||||
subscriber.onTick(mTickCount);
|
||||
}
|
||||
long endTimeNanos = System.nanoTime();
|
||||
stillHasListeners = true;
|
||||
if (subscriber.getTickInterval() > 0
|
||||
&& mTickCount % subscriber.getTickInterval() == 0)
|
||||
subscriber.onTick(mTickCount);
|
||||
}
|
||||
long endTimeNanos = System.nanoTime();
|
||||
|
||||
if (stillHasListeners && !mPendingRequest) {
|
||||
mHandler.postDelayed(this, TICK_INTERVAL_MILLIS
|
||||
- ((endTimeNanos - startTimeNanos) / 1000000));
|
||||
mPendingRequest = true;
|
||||
mTickCount++;
|
||||
} else {
|
||||
mPendingRequest = false;
|
||||
}
|
||||
}
|
||||
if (stillHasListeners && !mPendingRequest) {
|
||||
mHandler.postDelayed(this, TICK_INTERVAL_MILLIS
|
||||
- ((endTimeNanos - startTimeNanos) / 1000000));
|
||||
mPendingRequest = true;
|
||||
mTickCount++;
|
||||
} else {
|
||||
mPendingRequest = false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOn() {
|
||||
return mPendingRequest;
|
||||
}
|
||||
public boolean isOn() {
|
||||
return mPendingRequest;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
mForceStop = true;
|
||||
}
|
||||
public void stop() {
|
||||
mForceStop = true;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
public synchronized static Ticker getInstance() {
|
||||
if (sInstance == null) {
|
||||
sInstance = new Ticker();
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
public synchronized static Ticker getInstance() {
|
||||
if (sInstance == null) {
|
||||
sInstance = new Ticker();
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public void addSubscriber(TickSubscriber subscriber, Context host) {
|
||||
if (!mSubscribers.containsKey(subscriber) && subscriber != null) {
|
||||
mSubscribers.put(subscriber, null);
|
||||
startTicking(host);
|
||||
}
|
||||
}
|
||||
public void addSubscriber(TickSubscriber subscriber, Context host) {
|
||||
if (!mSubscribers.containsKey(subscriber) && subscriber != null) {
|
||||
mSubscribers.put(subscriber, null);
|
||||
startTicking(host);
|
||||
}
|
||||
}
|
||||
|
||||
private Ticker() {
|
||||
mSubscribers = new WeakHashMap<TickSubscriber, Object>();
|
||||
mTickerHosts = new WeakHashMap<Context, Object>();
|
||||
mEngine = new TickerEngine(this);
|
||||
}
|
||||
private Ticker() {
|
||||
mSubscribers = new WeakHashMap<TickSubscriber, Object>();
|
||||
mTickerHosts = new WeakHashMap<Context, Object>();
|
||||
mEngine = new TickerEngine(this);
|
||||
}
|
||||
|
||||
public void startTicking(Context host) {
|
||||
mTickerHosts.put(host, true);
|
||||
if (!mEngine.isOn())
|
||||
mEngine.run();
|
||||
}
|
||||
public void startTicking(Context host) {
|
||||
mTickerHosts.put(host, true);
|
||||
if (!mEngine.isOn())
|
||||
mEngine.run();
|
||||
}
|
||||
|
||||
public void stopTicking(Context host) {
|
||||
mTickerHosts.remove(host);
|
||||
if (mEngine.isOn() && mTickerHosts.isEmpty())
|
||||
mEngine.stop();
|
||||
}
|
||||
public void stopTicking(Context host) {
|
||||
mTickerHosts.remove(host);
|
||||
if (mEngine.isOn() && mTickerHosts.isEmpty())
|
||||
mEngine.stop();
|
||||
}
|
||||
}
|
||||
|
@ -9,59 +9,59 @@ import android.widget.TextSwitcher;
|
||||
import com.dougkeen.bart.model.TextProvider;
|
||||
|
||||
public class TimedTextSwitcher extends TextSwitcher implements
|
||||
Ticker.TickSubscriber {
|
||||
Ticker.TickSubscriber {
|
||||
|
||||
public TimedTextSwitcher(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setInstanceVarsFromAttrs(attrs);
|
||||
}
|
||||
public TimedTextSwitcher(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setInstanceVarsFromAttrs(attrs);
|
||||
}
|
||||
|
||||
public TimedTextSwitcher(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public TimedTextSwitcher(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
private void setInstanceVarsFromAttrs(AttributeSet attrs) {
|
||||
int tickInterval = attrs.getAttributeIntValue(
|
||||
"http://schemas.android.com/apk/res/com.dougkeen.bart",
|
||||
"tickInterval", 0);
|
||||
if (tickInterval > 0) {
|
||||
setTickInterval(tickInterval);
|
||||
}
|
||||
}
|
||||
private void setInstanceVarsFromAttrs(AttributeSet attrs) {
|
||||
int tickInterval = attrs.getAttributeIntValue(
|
||||
"http://schemas.android.com/apk/res/com.dougkeen.bart",
|
||||
"tickInterval", 0);
|
||||
if (tickInterval > 0) {
|
||||
setTickInterval(tickInterval);
|
||||
}
|
||||
}
|
||||
|
||||
private int mTickInterval;
|
||||
private TextProvider mTextProvider;
|
||||
private int mTickInterval;
|
||||
private TextProvider mTextProvider;
|
||||
|
||||
@Override
|
||||
public int getTickInterval() {
|
||||
return mTickInterval;
|
||||
}
|
||||
@Override
|
||||
public int getTickInterval() {
|
||||
return mTickInterval;
|
||||
}
|
||||
|
||||
public void setTickInterval(int tickInterval) {
|
||||
this.mTickInterval = tickInterval;
|
||||
}
|
||||
public void setTickInterval(int tickInterval) {
|
||||
this.mTickInterval = tickInterval;
|
||||
}
|
||||
|
||||
public void setTextProvider(TextProvider textProvider) {
|
||||
mTextProvider = textProvider;
|
||||
Ticker.getInstance().addSubscriber(this, getContext());
|
||||
}
|
||||
public void setTextProvider(TextProvider textProvider) {
|
||||
mTextProvider = textProvider;
|
||||
Ticker.getInstance().addSubscriber(this, getContext());
|
||||
}
|
||||
|
||||
private CharSequence mLastText;
|
||||
private CharSequence mLastText;
|
||||
|
||||
@Override
|
||||
public void setCurrentText(CharSequence text) {
|
||||
mLastText = text;
|
||||
super.setCurrentText(text);
|
||||
}
|
||||
@Override
|
||||
public void setCurrentText(CharSequence text) {
|
||||
mLastText = text;
|
||||
super.setCurrentText(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick(long tickNumber) {
|
||||
String text = mTextProvider.getText(tickNumber);
|
||||
if (StringUtils.isNotBlank(text)
|
||||
&& !StringUtils.equalsIgnoreCase(text, mLastText)) {
|
||||
mLastText = text;
|
||||
setText(text);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onTick(long tickNumber) {
|
||||
String text = mTextProvider.getText(tickNumber);
|
||||
if (StringUtils.isNotBlank(text)
|
||||
&& !StringUtils.equalsIgnoreCase(text, mLastText)) {
|
||||
mLastText = text;
|
||||
setText(text);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,167 +20,167 @@ import com.dougkeen.util.Observer;
|
||||
|
||||
public class YourTrainLayout extends RelativeLayout implements Checkable {
|
||||
|
||||
public YourTrainLayout(Context context) {
|
||||
super(context);
|
||||
assignLayout(context);
|
||||
}
|
||||
public YourTrainLayout(Context context) {
|
||||
super(context);
|
||||
assignLayout(context);
|
||||
}
|
||||
|
||||
public YourTrainLayout(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
assignLayout(context);
|
||||
}
|
||||
public YourTrainLayout(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
assignLayout(context);
|
||||
}
|
||||
|
||||
public YourTrainLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
assignLayout(context);
|
||||
}
|
||||
public YourTrainLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
assignLayout(context);
|
||||
}
|
||||
|
||||
public void assignLayout(Context context) {
|
||||
LayoutInflater.from(context).inflate(R.layout.your_train, this, true);
|
||||
}
|
||||
public void assignLayout(Context context) {
|
||||
LayoutInflater.from(context).inflate(R.layout.your_train, this, true);
|
||||
}
|
||||
|
||||
private boolean mChecked;
|
||||
private boolean mChecked;
|
||||
|
||||
private Departure mDeparture;
|
||||
private Departure mDeparture;
|
||||
|
||||
private final Observer<Integer> mAlarmLeadObserver = new Observer<Integer>() {
|
||||
@Override
|
||||
public void onUpdate(Integer newValue) {
|
||||
final Activity context = (Activity) getContext();
|
||||
if (context != null) {
|
||||
context.runOnUiThread(mUpdateAlarmIndicatorRunnable);
|
||||
}
|
||||
}
|
||||
};
|
||||
private final Observer<Integer> mAlarmLeadObserver = new Observer<Integer>() {
|
||||
@Override
|
||||
public void onUpdate(Integer newValue) {
|
||||
final Activity context = (Activity) getContext();
|
||||
if (context != null) {
|
||||
context.runOnUiThread(mUpdateAlarmIndicatorRunnable);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final Observer<Boolean> mAlarmPendingObserver = new Observer<Boolean>() {
|
||||
@Override
|
||||
public void onUpdate(Boolean newValue) {
|
||||
final Activity context = (Activity) getContext();
|
||||
if (context != null) {
|
||||
context.runOnUiThread(mUpdateAlarmIndicatorRunnable);
|
||||
}
|
||||
}
|
||||
};
|
||||
private final Observer<Boolean> mAlarmPendingObserver = new Observer<Boolean>() {
|
||||
@Override
|
||||
public void onUpdate(Boolean newValue) {
|
||||
final Activity context = (Activity) getContext();
|
||||
if (context != null) {
|
||||
context.runOnUiThread(mUpdateAlarmIndicatorRunnable);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return mChecked;
|
||||
}
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return mChecked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChecked(boolean checked) {
|
||||
mChecked = checked;
|
||||
setBackground();
|
||||
}
|
||||
@Override
|
||||
public void setChecked(boolean checked) {
|
||||
mChecked = checked;
|
||||
setBackground();
|
||||
}
|
||||
|
||||
private void setBackground() {
|
||||
if (isChecked()) {
|
||||
setBackgroundDrawable(getContext().getResources().getDrawable(
|
||||
R.color.blue_selection));
|
||||
} else {
|
||||
setBackgroundDrawable(getContext().getResources().getDrawable(
|
||||
R.color.gray));
|
||||
}
|
||||
}
|
||||
private void setBackground() {
|
||||
if (isChecked()) {
|
||||
setBackgroundDrawable(getContext().getResources().getDrawable(
|
||||
R.color.blue_selection));
|
||||
} else {
|
||||
setBackgroundDrawable(getContext().getResources().getDrawable(
|
||||
R.color.gray));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggle() {
|
||||
setChecked(!isChecked());
|
||||
}
|
||||
@Override
|
||||
public void toggle() {
|
||||
setChecked(!isChecked());
|
||||
}
|
||||
|
||||
public void updateFromBoardedDeparture() {
|
||||
final Departure boardedDeparture = ((BartRunnerApplication) ((Activity) getContext())
|
||||
.getApplication()).getBoardedDeparture();
|
||||
if (boardedDeparture == null)
|
||||
return;
|
||||
public void updateFromBoardedDeparture() {
|
||||
final Departure boardedDeparture = ((BartRunnerApplication) ((Activity) getContext())
|
||||
.getApplication()).getBoardedDeparture();
|
||||
if (boardedDeparture == null)
|
||||
return;
|
||||
|
||||
if (!boardedDeparture.equals(mDeparture)) {
|
||||
if (mDeparture != null) {
|
||||
mDeparture.getAlarmLeadTimeMinutesObservable()
|
||||
.unregisterObserver(mAlarmLeadObserver);
|
||||
mDeparture.getAlarmPendingObservable().unregisterObserver(
|
||||
mAlarmPendingObserver);
|
||||
}
|
||||
boardedDeparture.getAlarmLeadTimeMinutesObservable()
|
||||
.registerObserver(mAlarmLeadObserver);
|
||||
boardedDeparture.getAlarmPendingObservable().registerObserver(
|
||||
mAlarmPendingObserver);
|
||||
}
|
||||
if (!boardedDeparture.equals(mDeparture)) {
|
||||
if (mDeparture != null) {
|
||||
mDeparture.getAlarmLeadTimeMinutesObservable()
|
||||
.unregisterObserver(mAlarmLeadObserver);
|
||||
mDeparture.getAlarmPendingObservable().unregisterObserver(
|
||||
mAlarmPendingObserver);
|
||||
}
|
||||
boardedDeparture.getAlarmLeadTimeMinutesObservable()
|
||||
.registerObserver(mAlarmLeadObserver);
|
||||
boardedDeparture.getAlarmPendingObservable().registerObserver(
|
||||
mAlarmPendingObserver);
|
||||
}
|
||||
|
||||
mDeparture = boardedDeparture;
|
||||
mDeparture = boardedDeparture;
|
||||
|
||||
((TextView) findViewById(R.id.yourTrainDestinationText))
|
||||
.setText(boardedDeparture.getTrainDestination().toString());
|
||||
((TextView) findViewById(R.id.yourTrainDestinationText))
|
||||
.setText(boardedDeparture.getTrainDestination().toString());
|
||||
|
||||
((TextView) findViewById(R.id.yourTrainTrainLengthText))
|
||||
.setText(boardedDeparture.getTrainLengthAndPlatform());
|
||||
((TextView) findViewById(R.id.yourTrainTrainLengthText))
|
||||
.setText(boardedDeparture.getTrainLengthAndPlatform());
|
||||
|
||||
ImageView colorBar = (ImageView) findViewById(R.id.yourTrainDestinationColorBar);
|
||||
((GradientDrawable) colorBar.getDrawable()).setColor(Color
|
||||
.parseColor(boardedDeparture.getTrainDestinationColor()));
|
||||
ImageView bikeIcon = (ImageView) findViewById(R.id.yourTrainBikeIcon);
|
||||
if (boardedDeparture.isBikeAllowed()) {
|
||||
bikeIcon.setImageDrawable(getResources().getDrawable(
|
||||
R.drawable.bike));
|
||||
} else {
|
||||
bikeIcon.setImageDrawable(getResources().getDrawable(
|
||||
R.drawable.nobike));
|
||||
}
|
||||
if (boardedDeparture.getRequiresTransfer()) {
|
||||
((ImageView) findViewById(R.id.yourTrainXferIcon))
|
||||
.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
((ImageView) findViewById(R.id.yourTrainXferIcon))
|
||||
.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
ImageView colorBar = (ImageView) findViewById(R.id.yourTrainDestinationColorBar);
|
||||
((GradientDrawable) colorBar.getDrawable()).setColor(Color
|
||||
.parseColor(boardedDeparture.getTrainDestinationColor()));
|
||||
ImageView bikeIcon = (ImageView) findViewById(R.id.yourTrainBikeIcon);
|
||||
if (boardedDeparture.isBikeAllowed()) {
|
||||
bikeIcon.setImageDrawable(getResources().getDrawable(
|
||||
R.drawable.bike));
|
||||
} else {
|
||||
bikeIcon.setImageDrawable(getResources().getDrawable(
|
||||
R.drawable.nobike));
|
||||
}
|
||||
if (boardedDeparture.getRequiresTransfer()) {
|
||||
findViewById(R.id.yourTrainXferIcon)
|
||||
.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
findViewById(R.id.yourTrainXferIcon)
|
||||
.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
updateAlarmIndicator();
|
||||
updateAlarmIndicator();
|
||||
|
||||
CountdownTextView departureCountdown = (CountdownTextView) findViewById(R.id.yourTrainDepartureCountdown);
|
||||
CountdownTextView arrivalCountdown = (CountdownTextView) findViewById(R.id.yourTrainArrivalCountdown);
|
||||
CountdownTextView departureCountdown = (CountdownTextView) findViewById(R.id.yourTrainDepartureCountdown);
|
||||
CountdownTextView arrivalCountdown = (CountdownTextView) findViewById(R.id.yourTrainArrivalCountdown);
|
||||
|
||||
final TextProvider textProvider = new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
if (boardedDeparture.hasDeparted()) {
|
||||
return boardedDeparture.getCountdownText();
|
||||
} else {
|
||||
return "Leaves in " + boardedDeparture.getCountdownText()
|
||||
+ " " + boardedDeparture.getUncertaintyText();
|
||||
}
|
||||
}
|
||||
};
|
||||
departureCountdown.setText(textProvider.getText(0));
|
||||
departureCountdown.setTextProvider(textProvider);
|
||||
final TextProvider textProvider = new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
if (boardedDeparture.hasDeparted()) {
|
||||
return boardedDeparture.getCountdownText();
|
||||
} else {
|
||||
return "Leaves in " + boardedDeparture.getCountdownText()
|
||||
+ " " + boardedDeparture.getUncertaintyText();
|
||||
}
|
||||
}
|
||||
};
|
||||
departureCountdown.setText(textProvider.getText(0));
|
||||
departureCountdown.setTextProvider(textProvider);
|
||||
|
||||
arrivalCountdown.setText(boardedDeparture
|
||||
.getEstimatedArrivalMinutesLeftText(getContext()));
|
||||
arrivalCountdown.setTextProvider(new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
return boardedDeparture
|
||||
.getEstimatedArrivalMinutesLeftText(getContext());
|
||||
}
|
||||
});
|
||||
arrivalCountdown.setText(boardedDeparture
|
||||
.getEstimatedArrivalMinutesLeftText(getContext()));
|
||||
arrivalCountdown.setTextProvider(new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
return boardedDeparture
|
||||
.getEstimatedArrivalMinutesLeftText(getContext());
|
||||
}
|
||||
});
|
||||
|
||||
setBackground();
|
||||
}
|
||||
setBackground();
|
||||
}
|
||||
|
||||
private void updateAlarmIndicator() {
|
||||
if (!mDeparture.isAlarmPending()) {
|
||||
findViewById(R.id.alarmText).setVisibility(GONE);
|
||||
} else {
|
||||
findViewById(R.id.alarmText).setVisibility(VISIBLE);
|
||||
((TextView) findViewById(R.id.alarmText)).setText(String
|
||||
.valueOf(mDeparture.getAlarmLeadTimeMinutes()));
|
||||
}
|
||||
}
|
||||
private void updateAlarmIndicator() {
|
||||
if (!mDeparture.isAlarmPending()) {
|
||||
findViewById(R.id.alarmText).setVisibility(GONE);
|
||||
} else {
|
||||
findViewById(R.id.alarmText).setVisibility(VISIBLE);
|
||||
((TextView) findViewById(R.id.alarmText)).setText(String
|
||||
.valueOf(mDeparture.getAlarmLeadTimeMinutes()));
|
||||
}
|
||||
}
|
||||
|
||||
private final Runnable mUpdateAlarmIndicatorRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateAlarmIndicator();
|
||||
}
|
||||
};
|
||||
private final Runnable mUpdateAlarmIndicatorRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateAlarmIndicator();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -3,25 +3,25 @@ package com.dougkeen.bart.data;
|
||||
import android.database.Cursor;
|
||||
|
||||
public final class CursorUtils {
|
||||
private CursorUtils() {
|
||||
// Static only class
|
||||
}
|
||||
private CursorUtils() {
|
||||
// Static only class
|
||||
}
|
||||
|
||||
public static final void closeCursorQuietly(Cursor cursor) {
|
||||
if (cursor != null && !cursor.isClosed()) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
public static final void closeCursorQuietly(Cursor cursor) {
|
||||
if (cursor != null && !cursor.isClosed()) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static final String getString(Cursor cursor, RoutesColumns column) {
|
||||
return cursor.getString(cursor.getColumnIndex(column.string));
|
||||
}
|
||||
public static final String getString(Cursor cursor, RoutesColumns column) {
|
||||
return cursor.getString(cursor.getColumnIndex(column.string));
|
||||
}
|
||||
|
||||
public static final Long getLong(Cursor cursor, RoutesColumns column) {
|
||||
return cursor.getLong(cursor.getColumnIndex(column.string));
|
||||
}
|
||||
public static final Long getLong(Cursor cursor, RoutesColumns column) {
|
||||
return cursor.getLong(cursor.getColumnIndex(column.string));
|
||||
}
|
||||
|
||||
public static final Integer getInteger(Cursor cursor, RoutesColumns column) {
|
||||
return cursor.getInt(cursor.getColumnIndex(column.string));
|
||||
}
|
||||
public static final Integer getInteger(Cursor cursor, RoutesColumns column) {
|
||||
return cursor.getInt(cursor.getColumnIndex(column.string));
|
||||
}
|
||||
}
|
||||
|
@ -13,57 +13,57 @@ import com.dougkeen.bart.model.StationPair;
|
||||
|
||||
public class DatabaseHelper extends SQLiteOpenHelper {
|
||||
|
||||
private static final String DATABASE_NAME = "bart.dougkeen.db";
|
||||
private static final int DATABASE_VERSION = 6;
|
||||
private static final String DATABASE_NAME = "bart.dougkeen.db";
|
||||
private static final int DATABASE_VERSION = 6;
|
||||
|
||||
public static final String FAVORITES_TABLE_NAME = "Favorites";
|
||||
public static final String FAVORITES_TABLE_NAME = "Favorites";
|
||||
|
||||
private BartRunnerApplication app;
|
||||
private BartRunnerApplication app;
|
||||
|
||||
public DatabaseHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
app = (BartRunnerApplication) context.getApplicationContext();
|
||||
}
|
||||
public DatabaseHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
app = (BartRunnerApplication) context.getApplicationContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
}
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
}
|
||||
|
||||
private void createFavoritesTable(SQLiteDatabase db) {
|
||||
db.execSQL("CREATE TABLE IF NOT EXISTS " + FAVORITES_TABLE_NAME + " ("
|
||||
+ RoutesColumns._ID.getColumnDef() + " PRIMARY KEY, "
|
||||
+ RoutesColumns.FROM_STATION.getColumnDef() + ", "
|
||||
+ RoutesColumns.TO_STATION.getColumnDef() + ", "
|
||||
+ RoutesColumns.FARE.getColumnDef() + ", "
|
||||
+ RoutesColumns.FARE_LAST_UPDATED.getColumnDef() + ", "
|
||||
+ RoutesColumns.AVERAGE_TRIP_SAMPLE_COUNT.getColumnDef() + ", "
|
||||
+ RoutesColumns.AVERAGE_TRIP_LENGTH.getColumnDef() + ");");
|
||||
}
|
||||
private void createFavoritesTable(SQLiteDatabase db) {
|
||||
db.execSQL("CREATE TABLE IF NOT EXISTS " + FAVORITES_TABLE_NAME + " ("
|
||||
+ RoutesColumns._ID.getColumnDef() + " PRIMARY KEY, "
|
||||
+ RoutesColumns.FROM_STATION.getColumnDef() + ", "
|
||||
+ RoutesColumns.TO_STATION.getColumnDef() + ", "
|
||||
+ RoutesColumns.FARE.getColumnDef() + ", "
|
||||
+ RoutesColumns.FARE_LAST_UPDATED.getColumnDef() + ", "
|
||||
+ RoutesColumns.AVERAGE_TRIP_SAMPLE_COUNT.getColumnDef() + ", "
|
||||
+ RoutesColumns.AVERAGE_TRIP_LENGTH.getColumnDef() + ");");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
db.beginTransaction();
|
||||
try {
|
||||
createFavoritesTable(db);
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
db.beginTransaction();
|
||||
try {
|
||||
createFavoritesTable(db);
|
||||
|
||||
Cursor query = db.query(FAVORITES_TABLE_NAME, RoutesColumns.all(),
|
||||
null, null, null, null, null);
|
||||
Cursor query = db.query(FAVORITES_TABLE_NAME, RoutesColumns.all(),
|
||||
null, null, null, null, null);
|
||||
|
||||
List<StationPair> favorites = new ArrayList<StationPair>();
|
||||
List<StationPair> favorites = new ArrayList<StationPair>();
|
||||
|
||||
while (query.moveToNext()) {
|
||||
favorites.add(StationPair.createFromCursor(query));
|
||||
}
|
||||
while (query.moveToNext()) {
|
||||
favorites.add(StationPair.createFromCursor(query));
|
||||
}
|
||||
|
||||
query.close();
|
||||
query.close();
|
||||
|
||||
new FavoritesPersistence(app).persist(favorites);
|
||||
new FavoritesPersistence(app).persist(favorites);
|
||||
|
||||
db.execSQL("DROP TABLE " + FAVORITES_TABLE_NAME);
|
||||
db.execSQL("DROP TABLE " + FAVORITES_TABLE_NAME);
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
}
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,181 +28,181 @@ import com.dougkeen.bart.model.TextProvider;
|
||||
|
||||
public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
|
||||
|
||||
private Drawable noBikeDrawable;
|
||||
private Drawable bikeDrawable;
|
||||
private Drawable noBikeDrawable;
|
||||
private Drawable bikeDrawable;
|
||||
|
||||
public DepartureArrayAdapter(Context context, int textViewResourceId,
|
||||
Departure[] objects) {
|
||||
super(context, textViewResourceId, objects);
|
||||
assignBikeDrawables();
|
||||
}
|
||||
public DepartureArrayAdapter(Context context, int textViewResourceId,
|
||||
Departure[] objects) {
|
||||
super(context, textViewResourceId, objects);
|
||||
assignBikeDrawables();
|
||||
}
|
||||
|
||||
private void assignBikeDrawables() {
|
||||
noBikeDrawable = getContext().getResources().getDrawable(
|
||||
R.drawable.nobike);
|
||||
bikeDrawable = getContext().getResources().getDrawable(R.drawable.bike);
|
||||
}
|
||||
private void assignBikeDrawables() {
|
||||
noBikeDrawable = getContext().getResources().getDrawable(
|
||||
R.drawable.nobike);
|
||||
bikeDrawable = getContext().getResources().getDrawable(R.drawable.bike);
|
||||
}
|
||||
|
||||
public DepartureArrayAdapter(Context context, int resource,
|
||||
int textViewResourceId, Departure[] objects) {
|
||||
super(context, resource, textViewResourceId, objects);
|
||||
assignBikeDrawables();
|
||||
}
|
||||
public DepartureArrayAdapter(Context context, int resource,
|
||||
int textViewResourceId, Departure[] objects) {
|
||||
super(context, resource, textViewResourceId, objects);
|
||||
assignBikeDrawables();
|
||||
}
|
||||
|
||||
public DepartureArrayAdapter(Context context, int resource,
|
||||
int textViewResourceId, List<Departure> objects) {
|
||||
super(context, resource, textViewResourceId, objects);
|
||||
assignBikeDrawables();
|
||||
}
|
||||
public DepartureArrayAdapter(Context context, int resource,
|
||||
int textViewResourceId, List<Departure> objects) {
|
||||
super(context, resource, textViewResourceId, objects);
|
||||
assignBikeDrawables();
|
||||
}
|
||||
|
||||
public DepartureArrayAdapter(Context context, int resource,
|
||||
int textViewResourceId) {
|
||||
super(context, resource, textViewResourceId);
|
||||
assignBikeDrawables();
|
||||
}
|
||||
public DepartureArrayAdapter(Context context, int resource,
|
||||
int textViewResourceId) {
|
||||
super(context, resource, textViewResourceId);
|
||||
assignBikeDrawables();
|
||||
}
|
||||
|
||||
public DepartureArrayAdapter(Context context, int textViewResourceId,
|
||||
List<Departure> objects) {
|
||||
super(context, textViewResourceId, objects);
|
||||
assignBikeDrawables();
|
||||
}
|
||||
public DepartureArrayAdapter(Context context, int textViewResourceId,
|
||||
List<Departure> objects) {
|
||||
super(context, textViewResourceId, objects);
|
||||
assignBikeDrawables();
|
||||
}
|
||||
|
||||
public DepartureArrayAdapter(Context context, int textViewResourceId) {
|
||||
super(context, textViewResourceId);
|
||||
assignBikeDrawables();
|
||||
}
|
||||
public DepartureArrayAdapter(Context context, int textViewResourceId) {
|
||||
super(context, textViewResourceId);
|
||||
assignBikeDrawables();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View view;
|
||||
if (convertView != null
|
||||
&& convertView instanceof DepartureListItemLayout) {
|
||||
view = convertView;
|
||||
} else {
|
||||
view = new DepartureListItemLayout(getContext());
|
||||
}
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View view;
|
||||
if (convertView != null
|
||||
&& convertView instanceof DepartureListItemLayout) {
|
||||
view = convertView;
|
||||
} else {
|
||||
view = new DepartureListItemLayout(getContext());
|
||||
}
|
||||
|
||||
final Departure departure = getItem(position);
|
||||
final Departure departure = getItem(position);
|
||||
|
||||
((Checkable) view).setChecked(departure.isSelected());
|
||||
((Checkable) view).setChecked(departure.isSelected());
|
||||
|
||||
((TextView) view.findViewById(R.id.destinationText)).setText(departure
|
||||
.getTrainDestination().toString());
|
||||
((TextView) view.findViewById(R.id.destinationText)).setText(departure
|
||||
.getTrainDestination().toString());
|
||||
|
||||
final String arrivesAtDestinationPrefix = getContext().getString(
|
||||
R.string.arrives_at_destination);
|
||||
final String estimatedArrivalTimeText = departure
|
||||
.getEstimatedArrivalTimeText(getContext(), false);
|
||||
final String arrivesAtDestinationPrefix = getContext().getString(
|
||||
R.string.arrives_at_destination);
|
||||
final String estimatedArrivalTimeText = departure
|
||||
.getEstimatedArrivalTimeText(getContext(), false);
|
||||
|
||||
TextView estimatedArrival = (TextView) view
|
||||
.findViewById(R.id.estimatedArrival);
|
||||
if (estimatedArrival != null) {
|
||||
((TextView) view.findViewById(R.id.trainLengthText))
|
||||
.setText(departure.getTrainLengthAndPlatform());
|
||||
estimatedArrival.setText(arrivesAtDestinationPrefix
|
||||
+ estimatedArrivalTimeText);
|
||||
} else {
|
||||
TimedTextSwitcher textSwitcher = (TimedTextSwitcher) view
|
||||
.findViewById(R.id.trainLengthText);
|
||||
initTextSwitcher(textSwitcher,
|
||||
R.layout.train_length_arrival_textview);
|
||||
TextView estimatedArrival = (TextView) view
|
||||
.findViewById(R.id.estimatedArrival);
|
||||
if (estimatedArrival != null) {
|
||||
((TextView) view.findViewById(R.id.trainLengthText))
|
||||
.setText(departure.getTrainLengthAndPlatform());
|
||||
estimatedArrival.setText(arrivesAtDestinationPrefix
|
||||
+ estimatedArrivalTimeText);
|
||||
} else {
|
||||
TimedTextSwitcher textSwitcher = (TimedTextSwitcher) view
|
||||
.findViewById(R.id.trainLengthText);
|
||||
initTextSwitcher(textSwitcher,
|
||||
R.layout.train_length_arrival_textview);
|
||||
|
||||
if (!StringUtils.isBlank(estimatedArrivalTimeText)) {
|
||||
textSwitcher.setCurrentText(arrivesAtDestinationPrefix
|
||||
+ estimatedArrivalTimeText);
|
||||
} else {
|
||||
textSwitcher.setCurrentText(departure.getTrainLengthAndPlatform());
|
||||
}
|
||||
textSwitcher.setTextProvider(new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
if (tickNumber % 4 == 0) {
|
||||
return departure.getTrainLengthAndPlatform();
|
||||
} else {
|
||||
final String estimatedArrivalTimeText = departure
|
||||
.getEstimatedArrivalTimeText(getContext(), false);
|
||||
if (StringUtils.isBlank(estimatedArrivalTimeText)) {
|
||||
return "";
|
||||
} else {
|
||||
return arrivesAtDestinationPrefix
|
||||
+ estimatedArrivalTimeText;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!StringUtils.isBlank(estimatedArrivalTimeText)) {
|
||||
textSwitcher.setCurrentText(arrivesAtDestinationPrefix
|
||||
+ estimatedArrivalTimeText);
|
||||
} else {
|
||||
textSwitcher.setCurrentText(departure.getTrainLengthAndPlatform());
|
||||
}
|
||||
textSwitcher.setTextProvider(new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
if (tickNumber % 4 == 0) {
|
||||
return departure.getTrainLengthAndPlatform();
|
||||
} else {
|
||||
final String estimatedArrivalTimeText = departure
|
||||
.getEstimatedArrivalTimeText(getContext(), false);
|
||||
if (StringUtils.isBlank(estimatedArrivalTimeText)) {
|
||||
return "";
|
||||
} else {
|
||||
return arrivesAtDestinationPrefix
|
||||
+ estimatedArrivalTimeText;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ImageView colorBar = (ImageView) view
|
||||
.findViewById(R.id.destinationColorBar);
|
||||
((GradientDrawable) colorBar.getDrawable()).setColor(Color
|
||||
.parseColor(departure.getTrainDestinationColor()));
|
||||
CountdownTextView countdownTextView = (CountdownTextView) view
|
||||
.findViewById(R.id.countdown);
|
||||
countdownTextView.setText(departure.getCountdownText());
|
||||
countdownTextView.setTextProvider(new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
return departure.getCountdownText();
|
||||
}
|
||||
});
|
||||
ImageView colorBar = (ImageView) view
|
||||
.findViewById(R.id.destinationColorBar);
|
||||
((GradientDrawable) colorBar.getDrawable()).setColor(Color
|
||||
.parseColor(departure.getTrainDestinationColor()));
|
||||
CountdownTextView countdownTextView = (CountdownTextView) view
|
||||
.findViewById(R.id.countdown);
|
||||
countdownTextView.setText(departure.getCountdownText());
|
||||
countdownTextView.setTextProvider(new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
return departure.getCountdownText();
|
||||
}
|
||||
});
|
||||
|
||||
TextView departureTime = (TextView) view
|
||||
.findViewById(R.id.departureTime);
|
||||
TextView departureTime = (TextView) view
|
||||
.findViewById(R.id.departureTime);
|
||||
|
||||
if (departureTime != null) {
|
||||
((TextView) view.findViewById(R.id.uncertainty)).setText(departure
|
||||
.getUncertaintyText());
|
||||
departureTime.setText(departure
|
||||
.getEstimatedDepartureTimeText(getContext(), false));
|
||||
} else {
|
||||
TimedTextSwitcher uncertaintySwitcher = (TimedTextSwitcher) view
|
||||
.findViewById(R.id.uncertainty);
|
||||
initTextSwitcher(uncertaintySwitcher, R.layout.uncertainty_textview);
|
||||
if (departureTime != null) {
|
||||
((TextView) view.findViewById(R.id.uncertainty)).setText(departure
|
||||
.getUncertaintyText());
|
||||
departureTime.setText(departure
|
||||
.getEstimatedDepartureTimeText(getContext(), false));
|
||||
} else {
|
||||
TimedTextSwitcher uncertaintySwitcher = (TimedTextSwitcher) view
|
||||
.findViewById(R.id.uncertainty);
|
||||
initTextSwitcher(uncertaintySwitcher, R.layout.uncertainty_textview);
|
||||
|
||||
uncertaintySwitcher.setTextProvider(new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
if (tickNumber % 4 == 0) {
|
||||
return departure.getUncertaintyText();
|
||||
} else {
|
||||
return departure
|
||||
.getEstimatedDepartureTimeText(getContext(), false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
uncertaintySwitcher.setTextProvider(new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
if (tickNumber % 4 == 0) {
|
||||
return departure.getUncertaintyText();
|
||||
} else {
|
||||
return departure
|
||||
.getEstimatedDepartureTimeText(getContext(), false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ImageView bikeIcon = (ImageView) view.findViewById(R.id.bikeIcon);
|
||||
if (departure.isBikeAllowed()) {
|
||||
bikeIcon.setImageDrawable(bikeDrawable);
|
||||
} else {
|
||||
bikeIcon.setImageDrawable(noBikeDrawable);
|
||||
}
|
||||
if (departure.getRequiresTransfer()) {
|
||||
((ImageView) view.findViewById(R.id.xferIcon))
|
||||
.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
((ImageView) view.findViewById(R.id.xferIcon))
|
||||
.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
ImageView bikeIcon = (ImageView) view.findViewById(R.id.bikeIcon);
|
||||
if (departure.isBikeAllowed()) {
|
||||
bikeIcon.setImageDrawable(bikeDrawable);
|
||||
} else {
|
||||
bikeIcon.setImageDrawable(noBikeDrawable);
|
||||
}
|
||||
if (departure.getRequiresTransfer()) {
|
||||
view.findViewById(R.id.xferIcon)
|
||||
.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
view.findViewById(R.id.xferIcon)
|
||||
.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
private void initTextSwitcher(TextSwitcher textSwitcher,
|
||||
final int layoutView) {
|
||||
if (textSwitcher.getInAnimation() == null) {
|
||||
textSwitcher.setFactory(new ViewFactory() {
|
||||
public View makeView() {
|
||||
return LayoutInflater.from(getContext()).inflate(
|
||||
layoutView, null);
|
||||
}
|
||||
});
|
||||
private void initTextSwitcher(TextSwitcher textSwitcher,
|
||||
final int layoutView) {
|
||||
if (textSwitcher.getInAnimation() == null) {
|
||||
textSwitcher.setFactory(new ViewFactory() {
|
||||
public View makeView() {
|
||||
return LayoutInflater.from(getContext()).inflate(
|
||||
layoutView, null);
|
||||
}
|
||||
});
|
||||
|
||||
textSwitcher.setInAnimation(AnimationUtils.loadAnimation(
|
||||
getContext(), android.R.anim.slide_in_left));
|
||||
textSwitcher.setOutAnimation(AnimationUtils.loadAnimation(
|
||||
getContext(), android.R.anim.slide_out_right));
|
||||
}
|
||||
}
|
||||
textSwitcher.setInAnimation(AnimationUtils.loadAnimation(
|
||||
getContext(), android.R.anim.slide_in_left));
|
||||
textSwitcher.setOutAnimation(AnimationUtils.loadAnimation(
|
||||
getContext(), android.R.anim.slide_out_right));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,229 +34,229 @@ import com.dougkeen.bart.services.EtdService_;
|
||||
|
||||
public class FavoritesArrayAdapter extends ArrayAdapter<StationPair> {
|
||||
|
||||
private boolean mBound = false;
|
||||
private boolean mBound = false;
|
||||
|
||||
private EtdService mEtdService;
|
||||
private EtdService mEtdService;
|
||||
|
||||
private Activity mHostActivity;
|
||||
private Activity mHostActivity;
|
||||
|
||||
private Map<StationPair, EtdListener> mEtdListeners = new HashMap<StationPair, EtdListener>();
|
||||
private Map<StationPair, EtdListener> mEtdListeners = new HashMap<StationPair, EtdListener>();
|
||||
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
mEtdService = null;
|
||||
mBound = false;
|
||||
}
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
mEtdService = null;
|
||||
mBound = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
mEtdService = ((EtdServiceBinder) service).getService();
|
||||
mBound = true;
|
||||
if (!isEmpty()) {
|
||||
setUpEtdListeners();
|
||||
}
|
||||
}
|
||||
};
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
mEtdService = ((EtdServiceBinder) service).getService();
|
||||
mBound = true;
|
||||
if (!isEmpty()) {
|
||||
setUpEtdListeners();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public void setUpEtdListeners() {
|
||||
if (mBound && mEtdService != null) {
|
||||
for (int i = getCount() - 1; i >= 0; i--) {
|
||||
final StationPair item = getItem(i);
|
||||
mEtdListeners.put(item, new EtdListener(item, mEtdService));
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setUpEtdListeners() {
|
||||
if (mBound && mEtdService != null) {
|
||||
for (int i = getCount() - 1; i >= 0; i--) {
|
||||
final StationPair item = getItem(i);
|
||||
mEtdListeners.put(item, new EtdListener(item, mEtdService));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clearEtdListeners() {
|
||||
if (mBound && mEtdService != null) {
|
||||
for (EtdListener listener : mEtdListeners.values()) {
|
||||
listener.close(mEtdService);
|
||||
}
|
||||
mEtdListeners.clear();
|
||||
}
|
||||
}
|
||||
public void clearEtdListeners() {
|
||||
if (mBound && mEtdService != null) {
|
||||
for (EtdListener listener : mEtdListeners.values()) {
|
||||
listener.close(mEtdService);
|
||||
}
|
||||
mEtdListeners.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean areEtdListenersActive() {
|
||||
return !mEtdListeners.isEmpty();
|
||||
}
|
||||
public boolean areEtdListenersActive() {
|
||||
return !mEtdListeners.isEmpty();
|
||||
}
|
||||
|
||||
public FavoritesArrayAdapter(Context context, int textViewResourceId,
|
||||
List<StationPair> objects) {
|
||||
super(context, textViewResourceId, objects);
|
||||
mHostActivity = (Activity) context;
|
||||
mHostActivity.bindService(EtdService_.intent(mHostActivity).get(),
|
||||
mConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
public FavoritesArrayAdapter(Context context, int textViewResourceId,
|
||||
List<StationPair> objects) {
|
||||
super(context, textViewResourceId, objects);
|
||||
mHostActivity = (Activity) context;
|
||||
mHostActivity.bindService(EtdService_.intent(mHostActivity).get(),
|
||||
mConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (mBound) {
|
||||
mHostActivity.unbindService(mConnection);
|
||||
}
|
||||
}
|
||||
public void close() {
|
||||
if (mBound) {
|
||||
mHostActivity.unbindService(mConnection);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(StationPair object) {
|
||||
super.add(object);
|
||||
if (mEtdService != null && mBound) {
|
||||
mEtdListeners.put(object, new EtdListener(object, mEtdService));
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void add(StationPair object) {
|
||||
super.add(object);
|
||||
if (mEtdService != null && mBound) {
|
||||
mEtdListeners.put(object, new EtdListener(object, mEtdService));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(StationPair object) {
|
||||
super.remove(object);
|
||||
if (mEtdListeners.containsKey(object) && mEtdService != null & mBound) {
|
||||
mEtdListeners.get(object).close(mEtdService);
|
||||
mEtdListeners.remove(object);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void remove(StationPair object) {
|
||||
super.remove(object);
|
||||
if (mEtdListeners.containsKey(object) && mEtdService != null & mBound) {
|
||||
mEtdListeners.get(object).close(mEtdService);
|
||||
mEtdListeners.remove(object);
|
||||
}
|
||||
}
|
||||
|
||||
public void move(StationPair object, int to) {
|
||||
super.remove(object);
|
||||
super.insert(object, to);
|
||||
}
|
||||
public void move(StationPair object, int to) {
|
||||
super.remove(object);
|
||||
super.insert(object, to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
clearEtdListeners();
|
||||
}
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
clearEtdListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View view;
|
||||
if (convertView != null && convertView instanceof RelativeLayout) {
|
||||
view = convertView;
|
||||
} else {
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
view = inflater.inflate(R.layout.favorite_listing, parent, false);
|
||||
}
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View view;
|
||||
if (convertView != null && convertView instanceof RelativeLayout) {
|
||||
view = convertView;
|
||||
} else {
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
view = inflater.inflate(R.layout.favorite_listing, parent, false);
|
||||
}
|
||||
|
||||
final StationPair pair = getItem(position);
|
||||
final StationPair pair = getItem(position);
|
||||
|
||||
final EtdListener etdListener = mEtdListeners.get(pair);
|
||||
final EtdListener etdListener = mEtdListeners.get(pair);
|
||||
|
||||
final TimedTextSwitcher uncertaintyTextSwitcher = (TimedTextSwitcher) view
|
||||
.findViewById(R.id.uncertainty);
|
||||
initTextSwitcher(uncertaintyTextSwitcher);
|
||||
final TimedTextSwitcher uncertaintyTextSwitcher = (TimedTextSwitcher) view
|
||||
.findViewById(R.id.uncertainty);
|
||||
initTextSwitcher(uncertaintyTextSwitcher);
|
||||
|
||||
if (etdListener == null || etdListener.getFirstDeparture() == null) {
|
||||
uncertaintyTextSwitcher.setCurrentText(pair.getFare());
|
||||
} else {
|
||||
CountdownTextView countdownTextView = (CountdownTextView) view
|
||||
.findViewById(R.id.countdownText);
|
||||
countdownTextView.setText(etdListener.getFirstDeparture()
|
||||
.getCountdownText());
|
||||
countdownTextView.setTextProvider(new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
return etdListener.getFirstDeparture().getCountdownText();
|
||||
}
|
||||
});
|
||||
if (etdListener == null || etdListener.getFirstDeparture() == null) {
|
||||
uncertaintyTextSwitcher.setCurrentText(pair.getFare());
|
||||
} else {
|
||||
CountdownTextView countdownTextView = (CountdownTextView) view
|
||||
.findViewById(R.id.countdownText);
|
||||
countdownTextView.setText(etdListener.getFirstDeparture()
|
||||
.getCountdownText());
|
||||
countdownTextView.setTextProvider(new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
return etdListener.getFirstDeparture().getCountdownText();
|
||||
}
|
||||
});
|
||||
|
||||
final String uncertaintyText = etdListener.getFirstDeparture()
|
||||
.getUncertaintyText();
|
||||
if (!StringUtils.isBlank(uncertaintyText)) {
|
||||
uncertaintyTextSwitcher.setCurrentText(uncertaintyText);
|
||||
} else {
|
||||
uncertaintyTextSwitcher.setCurrentText(pair.getFare());
|
||||
}
|
||||
uncertaintyTextSwitcher.setTextProvider(new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
final String arrive = etdListener.getFirstDeparture()
|
||||
.getEstimatedArrivalTimeText(getContext(), true);
|
||||
int mod = StringUtils.isNotBlank(arrive) ? 8 : 6;
|
||||
if (tickNumber % mod <= 1) {
|
||||
return pair.getFare();
|
||||
} else if (tickNumber % mod <= 3) {
|
||||
return "Dep "
|
||||
+ etdListener.getFirstDeparture()
|
||||
.getEstimatedDepartureTimeText(
|
||||
getContext(), true);
|
||||
} else if (mod == 8 && tickNumber % mod <= 5) {
|
||||
return "Arr " + arrive;
|
||||
} else {
|
||||
return etdListener.getFirstDeparture()
|
||||
.getUncertaintyText();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
final String uncertaintyText = etdListener.getFirstDeparture()
|
||||
.getUncertaintyText();
|
||||
if (!StringUtils.isBlank(uncertaintyText)) {
|
||||
uncertaintyTextSwitcher.setCurrentText(uncertaintyText);
|
||||
} else {
|
||||
uncertaintyTextSwitcher.setCurrentText(pair.getFare());
|
||||
}
|
||||
uncertaintyTextSwitcher.setTextProvider(new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
final String arrive = etdListener.getFirstDeparture()
|
||||
.getEstimatedArrivalTimeText(getContext(), true);
|
||||
int mod = StringUtils.isNotBlank(arrive) ? 8 : 6;
|
||||
if (tickNumber % mod <= 1) {
|
||||
return pair.getFare();
|
||||
} else if (tickNumber % mod <= 3) {
|
||||
return "Dep "
|
||||
+ etdListener.getFirstDeparture()
|
||||
.getEstimatedDepartureTimeText(
|
||||
getContext(), true);
|
||||
} else if (mod == 8 && tickNumber % mod <= 5) {
|
||||
return "Arr " + arrive;
|
||||
} else {
|
||||
return etdListener.getFirstDeparture()
|
||||
.getUncertaintyText();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
((TextView) view.findViewById(R.id.originText)).setText(pair
|
||||
.getOrigin().name);
|
||||
((TextView) view.findViewById(R.id.destinationText)).setText(pair
|
||||
.getDestination().name);
|
||||
((TextView) view.findViewById(R.id.originText)).setText(pair
|
||||
.getOrigin().name);
|
||||
((TextView) view.findViewById(R.id.destinationText)).setText(pair
|
||||
.getDestination().name);
|
||||
|
||||
return view;
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
private void initTextSwitcher(TextSwitcher textSwitcher) {
|
||||
if (textSwitcher.getInAnimation() == null) {
|
||||
textSwitcher.setFactory(new ViewFactory() {
|
||||
public View makeView() {
|
||||
return LayoutInflater.from(getContext()).inflate(
|
||||
R.layout.uncertainty_textview, null);
|
||||
}
|
||||
});
|
||||
private void initTextSwitcher(TextSwitcher textSwitcher) {
|
||||
if (textSwitcher.getInAnimation() == null) {
|
||||
textSwitcher.setFactory(new ViewFactory() {
|
||||
public View makeView() {
|
||||
return LayoutInflater.from(getContext()).inflate(
|
||||
R.layout.uncertainty_textview, null);
|
||||
}
|
||||
});
|
||||
|
||||
textSwitcher.setInAnimation(AnimationUtils.loadAnimation(
|
||||
getContext(), android.R.anim.slide_in_left));
|
||||
textSwitcher.setOutAnimation(AnimationUtils.loadAnimation(
|
||||
getContext(), android.R.anim.slide_out_right));
|
||||
}
|
||||
}
|
||||
textSwitcher.setInAnimation(AnimationUtils.loadAnimation(
|
||||
getContext(), android.R.anim.slide_in_left));
|
||||
textSwitcher.setOutAnimation(AnimationUtils.loadAnimation(
|
||||
getContext(), android.R.anim.slide_out_right));
|
||||
}
|
||||
}
|
||||
|
||||
private class EtdListener implements EtdServiceListener {
|
||||
private class EtdListener implements EtdServiceListener {
|
||||
|
||||
private final StationPair mStationPair;
|
||||
private final StationPair mStationPair;
|
||||
|
||||
private Departure firstDeparture;
|
||||
private Departure firstDeparture;
|
||||
|
||||
protected EtdListener(StationPair mStationPair, EtdService etdService) {
|
||||
super();
|
||||
this.mStationPair = mStationPair;
|
||||
etdService.registerListener(this, true);
|
||||
}
|
||||
protected EtdListener(StationPair mStationPair, EtdService etdService) {
|
||||
super();
|
||||
this.mStationPair = mStationPair;
|
||||
etdService.registerListener(this, true);
|
||||
}
|
||||
|
||||
protected void close(EtdService etdService) {
|
||||
etdService.unregisterListener(this);
|
||||
}
|
||||
protected void close(EtdService etdService) {
|
||||
etdService.unregisterListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onETDChanged(List<Departure> departures) {
|
||||
for (Departure departure : departures) {
|
||||
if (!departure.hasDeparted()) {
|
||||
if (!departure.equals(firstDeparture)) {
|
||||
firstDeparture = departure;
|
||||
FavoritesArrayAdapter.this.notifyDataSetChanged();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onETDChanged(List<Departure> departures) {
|
||||
for (Departure departure : departures) {
|
||||
if (!departure.hasDeparted()) {
|
||||
if (!departure.equals(firstDeparture)) {
|
||||
firstDeparture = departure;
|
||||
FavoritesArrayAdapter.this.notifyDataSetChanged();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String errorMessage) {
|
||||
}
|
||||
@Override
|
||||
public void onError(String errorMessage) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestStarted() {
|
||||
}
|
||||
@Override
|
||||
public void onRequestStarted() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestEnded() {
|
||||
}
|
||||
@Override
|
||||
public void onRequestEnded() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public StationPair getStationPair() {
|
||||
return mStationPair;
|
||||
}
|
||||
@Override
|
||||
public StationPair getStationPair() {
|
||||
return mStationPair;
|
||||
}
|
||||
|
||||
public Departure getFirstDeparture() {
|
||||
return firstDeparture;
|
||||
}
|
||||
}
|
||||
public Departure getFirstDeparture() {
|
||||
return firstDeparture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,46 +18,46 @@ import com.googlecode.androidannotations.annotations.EBean;
|
||||
|
||||
@EBean
|
||||
public class FavoritesPersistence {
|
||||
private static final String TAG = "FavoritesPersistence";
|
||||
private static final String TAG = "FavoritesPersistence";
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
private BartRunnerApplication app;
|
||||
private BartRunnerApplication app;
|
||||
|
||||
public FavoritesPersistence(Context context) {
|
||||
app = (BartRunnerApplication) context.getApplicationContext();
|
||||
}
|
||||
public FavoritesPersistence(Context context) {
|
||||
app = (BartRunnerApplication) context.getApplicationContext();
|
||||
}
|
||||
|
||||
public void persist(List<StationPair> favorites) {
|
||||
FileOutputStream outputStream = null;
|
||||
try {
|
||||
outputStream = app
|
||||
.openFileOutput("favorites", Context.MODE_PRIVATE);
|
||||
objectMapper.writeValue(outputStream, favorites);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Could not write favorites file", e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(outputStream);
|
||||
}
|
||||
}
|
||||
public void persist(List<StationPair> favorites) {
|
||||
FileOutputStream outputStream = null;
|
||||
try {
|
||||
outputStream = app
|
||||
.openFileOutput("favorites", Context.MODE_PRIVATE);
|
||||
objectMapper.writeValue(outputStream, favorites);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Could not write favorites file", e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(outputStream);
|
||||
}
|
||||
}
|
||||
|
||||
public List<StationPair> restore() {
|
||||
for (String file : app.fileList()) {
|
||||
if ("favorites".equals(file)) {
|
||||
FileInputStream inputStream = null;
|
||||
try {
|
||||
inputStream = app.openFileInput("favorites");
|
||||
return objectMapper.readValue(inputStream,
|
||||
new TypeReference<ArrayList<StationPair>>() {
|
||||
});
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Could not read favorites file", e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
public List<StationPair> restore() {
|
||||
for (String file : app.fileList()) {
|
||||
if ("favorites".equals(file)) {
|
||||
FileInputStream inputStream = null;
|
||||
try {
|
||||
inputStream = app.openFileInput("favorites");
|
||||
return objectMapper.readValue(inputStream,
|
||||
new TypeReference<ArrayList<StationPair>>() {
|
||||
});
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Could not read favorites file", e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayList<StationPair>();
|
||||
}
|
||||
return new ArrayList<StationPair>();
|
||||
}
|
||||
}
|
||||
|
@ -1,33 +1,33 @@
|
||||
package com.dougkeen.bart.data;
|
||||
|
||||
public enum RoutesColumns {
|
||||
_ID("_id", "INTEGER", false), FROM_STATION("FROM_STATION", "TEXT", false), TO_STATION(
|
||||
"TO_STATION", "TEXT", false), FARE("FARE", "TEXT", true), FARE_LAST_UPDATED(
|
||||
"FARE_LAST_UPDATED", "INTEGER", true), AVERAGE_TRIP_SAMPLE_COUNT(
|
||||
"AVE_TRIP_SAMPLE_COUNT", "INTEGER", true), AVERAGE_TRIP_LENGTH(
|
||||
"AVE_TRIP_LENGTH", "INTEGER", true);
|
||||
_ID("_id", "INTEGER", false), FROM_STATION("FROM_STATION", "TEXT", false), TO_STATION(
|
||||
"TO_STATION", "TEXT", false), FARE("FARE", "TEXT", true), FARE_LAST_UPDATED(
|
||||
"FARE_LAST_UPDATED", "INTEGER", true), AVERAGE_TRIP_SAMPLE_COUNT(
|
||||
"AVE_TRIP_SAMPLE_COUNT", "INTEGER", true), AVERAGE_TRIP_LENGTH(
|
||||
"AVE_TRIP_LENGTH", "INTEGER", true);
|
||||
|
||||
// This class cannot be instantiated
|
||||
private RoutesColumns(String string, String type, Boolean nullable) {
|
||||
this.string = string;
|
||||
this.sqliteType = type;
|
||||
this.nullable = nullable;
|
||||
}
|
||||
// This class cannot be instantiated
|
||||
RoutesColumns(String string, String type, Boolean nullable) {
|
||||
this.string = string;
|
||||
this.sqliteType = type;
|
||||
this.nullable = nullable;
|
||||
}
|
||||
|
||||
public final String string;
|
||||
public final String sqliteType;
|
||||
public final Boolean nullable;
|
||||
public final String string;
|
||||
public final String sqliteType;
|
||||
public final Boolean nullable;
|
||||
|
||||
protected String getColumnDef() {
|
||||
return string + " " + sqliteType + (nullable ? "" : " NOT NULL");
|
||||
}
|
||||
protected String getColumnDef() {
|
||||
return string + " " + sqliteType + (nullable ? "" : " NOT NULL");
|
||||
}
|
||||
|
||||
public static String[] all() {
|
||||
final RoutesColumns[] values = RoutesColumns.values();
|
||||
String[] returnArray = new String[values.length];
|
||||
for (int i = values.length - 1; i >= 0; i--) {
|
||||
returnArray[i] = values[i].string;
|
||||
}
|
||||
return returnArray;
|
||||
}
|
||||
public static String[] all() {
|
||||
final RoutesColumns[] values = RoutesColumns.values();
|
||||
String[] returnArray = new String[values.length];
|
||||
for (int i = values.length - 1; i >= 0; i--) {
|
||||
returnArray[i] = values[i].string;
|
||||
}
|
||||
return returnArray;
|
||||
}
|
||||
}
|
||||
|
@ -4,86 +4,86 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Alert {
|
||||
private String id;
|
||||
private String type;
|
||||
private String description;
|
||||
private String postedTime;
|
||||
private String expiresTime;
|
||||
private String id;
|
||||
private String type;
|
||||
private String description;
|
||||
private String postedTime;
|
||||
private String expiresTime;
|
||||
|
||||
public Alert(String id) {
|
||||
super();
|
||||
this.id = id;
|
||||
}
|
||||
public Alert(String id) {
|
||||
super();
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getPostedTime() {
|
||||
return postedTime;
|
||||
}
|
||||
public String getPostedTime() {
|
||||
return postedTime;
|
||||
}
|
||||
|
||||
public void setPostedTime(String postedTime) {
|
||||
this.postedTime = postedTime;
|
||||
}
|
||||
public void setPostedTime(String postedTime) {
|
||||
this.postedTime = postedTime;
|
||||
}
|
||||
|
||||
public String getExpiresTime() {
|
||||
return expiresTime;
|
||||
}
|
||||
public String getExpiresTime() {
|
||||
return expiresTime;
|
||||
}
|
||||
|
||||
public void setExpiresTime(String expiresTime) {
|
||||
this.expiresTime = expiresTime;
|
||||
}
|
||||
public void setExpiresTime(String expiresTime) {
|
||||
this.expiresTime = expiresTime;
|
||||
}
|
||||
|
||||
public static class AlertList {
|
||||
private List<Alert> alerts;
|
||||
private boolean noDelaysReported;
|
||||
public static class AlertList {
|
||||
private List<Alert> alerts;
|
||||
private boolean noDelaysReported;
|
||||
|
||||
public List<Alert> getAlerts() {
|
||||
if (alerts == null) {
|
||||
alerts = new ArrayList<Alert>();
|
||||
}
|
||||
return alerts;
|
||||
}
|
||||
public List<Alert> getAlerts() {
|
||||
if (alerts == null) {
|
||||
alerts = new ArrayList<Alert>();
|
||||
}
|
||||
return alerts;
|
||||
}
|
||||
|
||||
public void addAlert(Alert alert) {
|
||||
getAlerts().add(alert);
|
||||
}
|
||||
public void addAlert(Alert alert) {
|
||||
getAlerts().add(alert);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
getAlerts().clear();
|
||||
}
|
||||
public void clear() {
|
||||
getAlerts().clear();
|
||||
}
|
||||
|
||||
public boolean hasAlerts() {
|
||||
return !getAlerts().isEmpty();
|
||||
}
|
||||
public boolean hasAlerts() {
|
||||
return !getAlerts().isEmpty();
|
||||
}
|
||||
|
||||
public boolean areNoDelaysReported() {
|
||||
return noDelaysReported;
|
||||
}
|
||||
public boolean areNoDelaysReported() {
|
||||
return noDelaysReported;
|
||||
}
|
||||
|
||||
public void setNoDelaysReported(boolean noDelaysReported) {
|
||||
this.noDelaysReported = noDelaysReported;
|
||||
}
|
||||
}
|
||||
public void setNoDelaysReported(boolean noDelaysReported) {
|
||||
this.noDelaysReported = noDelaysReported;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,19 +3,19 @@ package com.dougkeen.bart.model;
|
||||
import android.net.Uri;
|
||||
|
||||
public class Constants {
|
||||
public static final String AUTHORITY = "com.dougkeen.bart.dataprovider";
|
||||
public static final String FAVORITE_CONTENT_TYPE = "vnd.android.cursor.dir/com.dougkeen.bart.favorite";
|
||||
public static final String ARBITRARY_ROUTE_UNDEFINED_TYPE = "vnd.android.cursor.dir/com.dougkeen.bart.arbitraryroute";
|
||||
public static final String ARBITRARY_ROUTE_TYPE = "vnd.android.cursor.item/com.dougkeen.bart.arbitraryroute";
|
||||
public static final String FAVORITE_CONTENT_ITEM_TYPE = "vnd.android.cursor.item/com.dougkeen.bart.favorite";
|
||||
public static final Uri FAVORITE_CONTENT_URI = Uri.parse("content://"
|
||||
+ AUTHORITY + "/favorites");
|
||||
public static final Uri ARBITRARY_ROUTE_CONTENT_URI_ROOT = Uri
|
||||
.parse("content://" + AUTHORITY + "/route");
|
||||
public static final String MAP_URL = "http://m.bart.gov/images/global/system-map29.gif";
|
||||
public static final String AUTHORITY = "com.dougkeen.bart.dataprovider";
|
||||
public static final String FAVORITE_CONTENT_TYPE = "vnd.android.cursor.dir/com.dougkeen.bart.favorite";
|
||||
public static final String ARBITRARY_ROUTE_UNDEFINED_TYPE = "vnd.android.cursor.dir/com.dougkeen.bart.arbitraryroute";
|
||||
public static final String ARBITRARY_ROUTE_TYPE = "vnd.android.cursor.item/com.dougkeen.bart.arbitraryroute";
|
||||
public static final String FAVORITE_CONTENT_ITEM_TYPE = "vnd.android.cursor.item/com.dougkeen.bart.favorite";
|
||||
public static final Uri FAVORITE_CONTENT_URI = Uri.parse("content://"
|
||||
+ AUTHORITY + "/favorites");
|
||||
public static final Uri ARBITRARY_ROUTE_CONTENT_URI_ROOT = Uri
|
||||
.parse("content://" + AUTHORITY + "/route");
|
||||
public static final String MAP_URL = "http://m.bart.gov/images/global/system-map29.gif";
|
||||
|
||||
public static final String TAG = "com.dougkeen.BartRunner";
|
||||
public static final String API_KEY = "5LD9-IAYI-TRAT-MHHW";
|
||||
public static final String ACTION_ALARM = "com.dougkeen.action.ALARM";
|
||||
public static final String STATION_PAIR_EXTRA = "StationPair";
|
||||
public static final String TAG = "com.dougkeen.BartRunner";
|
||||
public static final String API_KEY = "5LD9-IAYI-TRAT-MHHW";
|
||||
public static final String ACTION_ALARM = "com.dougkeen.action.ALARM";
|
||||
public static final String STATION_PAIR_EXTRA = "StationPair";
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,108 +8,108 @@ import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
public enum Line {
|
||||
RED(false, Station.MLBR, Station.SBRN, Station.SSAN, Station.COLM,
|
||||
Station.DALY, Station.BALB, Station.GLEN, Station._24TH,
|
||||
Station._16TH, Station.CIVC, Station.POWL, Station.MONT,
|
||||
Station.EMBR, Station.WOAK, Station._12TH, Station._19TH,
|
||||
Station.MCAR, Station.ASHB, Station.DBRK, Station.NBRK,
|
||||
Station.PLZA, Station.DELN, Station.RICH),
|
||||
ORANGE(false, Station.FRMT, Station.UCTY, Station.SHAY, Station.HAYW,
|
||||
Station.BAYF, Station.SANL, Station.COLS, Station.FTVL,
|
||||
Station.LAKE, Station._12TH, Station._19TH, Station.MCAR,
|
||||
Station.ASHB, Station.DBRK, Station.NBRK, Station.PLZA,
|
||||
Station.DELN, Station.RICH),
|
||||
YELLOW(false, Station.MLBR, Station.SFIA, Station.SBRN, Station.SSAN,
|
||||
Station.COLM, Station.DALY, Station.BALB, Station.GLEN,
|
||||
Station._24TH, Station._16TH, Station.CIVC, Station.POWL,
|
||||
Station.MONT, Station.EMBR, Station.WOAK, Station._12TH,
|
||||
Station._19TH, Station.MCAR, Station.ROCK, Station.ORIN,
|
||||
Station.LAFY, Station.WCRK, Station.PHIL, Station.CONC,
|
||||
Station.NCON, Station.PITT),
|
||||
BLUE(true, Station.DALY, Station.BALB, Station.GLEN, Station._24TH,
|
||||
Station._16TH, Station.CIVC, Station.POWL, Station.MONT,
|
||||
Station.EMBR, Station.WOAK, Station.LAKE, Station.FTVL,
|
||||
Station.COLS, Station.SANL, Station.BAYF, Station.CAST,
|
||||
Station.WDUB, Station.DUBL),
|
||||
GREEN(true, Station.DALY, Station.BALB, Station.GLEN, Station._24TH,
|
||||
Station._16TH, Station.CIVC, Station.POWL, Station.MONT,
|
||||
Station.EMBR, Station.WOAK, Station.LAKE, Station.FTVL,
|
||||
Station.COLS, Station.SANL, Station.BAYF, Station.HAYW,
|
||||
Station.SHAY, Station.UCTY, Station.FRMT),
|
||||
YELLOW_ORANGE_SCHEDULED_TRANSFER(YELLOW, ORANGE, Station.MLBR,
|
||||
Station.SFIA, Station.SBRN, Station.SSAN, Station.COLM,
|
||||
Station.DALY, Station.BALB, Station.GLEN, Station._24TH,
|
||||
Station._16TH, Station.CIVC, Station.POWL, Station.MONT,
|
||||
Station.EMBR, Station.WOAK, Station.ASHB, Station.DBRK,
|
||||
Station.NBRK, Station.PLZA, Station.DELN, Station.RICH);
|
||||
RED(false, Station.MLBR, Station.SBRN, Station.SSAN, Station.COLM,
|
||||
Station.DALY, Station.BALB, Station.GLEN, Station._24TH,
|
||||
Station._16TH, Station.CIVC, Station.POWL, Station.MONT,
|
||||
Station.EMBR, Station.WOAK, Station._12TH, Station._19TH,
|
||||
Station.MCAR, Station.ASHB, Station.DBRK, Station.NBRK,
|
||||
Station.PLZA, Station.DELN, Station.RICH),
|
||||
ORANGE(false, Station.FRMT, Station.UCTY, Station.SHAY, Station.HAYW,
|
||||
Station.BAYF, Station.SANL, Station.COLS, Station.FTVL,
|
||||
Station.LAKE, Station._12TH, Station._19TH, Station.MCAR,
|
||||
Station.ASHB, Station.DBRK, Station.NBRK, Station.PLZA,
|
||||
Station.DELN, Station.RICH),
|
||||
YELLOW(false, Station.MLBR, Station.SFIA, Station.SBRN, Station.SSAN,
|
||||
Station.COLM, Station.DALY, Station.BALB, Station.GLEN,
|
||||
Station._24TH, Station._16TH, Station.CIVC, Station.POWL,
|
||||
Station.MONT, Station.EMBR, Station.WOAK, Station._12TH,
|
||||
Station._19TH, Station.MCAR, Station.ROCK, Station.ORIN,
|
||||
Station.LAFY, Station.WCRK, Station.PHIL, Station.CONC,
|
||||
Station.NCON, Station.PITT),
|
||||
BLUE(true, Station.DALY, Station.BALB, Station.GLEN, Station._24TH,
|
||||
Station._16TH, Station.CIVC, Station.POWL, Station.MONT,
|
||||
Station.EMBR, Station.WOAK, Station.LAKE, Station.FTVL,
|
||||
Station.COLS, Station.SANL, Station.BAYF, Station.CAST,
|
||||
Station.WDUB, Station.DUBL),
|
||||
GREEN(true, Station.DALY, Station.BALB, Station.GLEN, Station._24TH,
|
||||
Station._16TH, Station.CIVC, Station.POWL, Station.MONT,
|
||||
Station.EMBR, Station.WOAK, Station.LAKE, Station.FTVL,
|
||||
Station.COLS, Station.SANL, Station.BAYF, Station.HAYW,
|
||||
Station.SHAY, Station.UCTY, Station.FRMT),
|
||||
YELLOW_ORANGE_SCHEDULED_TRANSFER(YELLOW, ORANGE, Station.MLBR,
|
||||
Station.SFIA, Station.SBRN, Station.SSAN, Station.COLM,
|
||||
Station.DALY, Station.BALB, Station.GLEN, Station._24TH,
|
||||
Station._16TH, Station.CIVC, Station.POWL, Station.MONT,
|
||||
Station.EMBR, Station.WOAK, Station.ASHB, Station.DBRK,
|
||||
Station.NBRK, Station.PLZA, Station.DELN, Station.RICH);
|
||||
|
||||
public final List<Station> stations;
|
||||
public final List<Station> stations;
|
||||
|
||||
protected final boolean directionMayInvert;
|
||||
protected final boolean directionMayInvert;
|
||||
|
||||
protected final boolean requiresTransfer;
|
||||
protected final boolean requiresTransfer;
|
||||
|
||||
protected final Line transferLine1;
|
||||
protected final Line transferLine1;
|
||||
|
||||
protected final Line transferLine2;
|
||||
protected final Line transferLine2;
|
||||
|
||||
private Line(boolean directionMayInvert, Station... stationArray) {
|
||||
this.requiresTransfer = false;
|
||||
this.directionMayInvert = directionMayInvert;
|
||||
stations = Arrays.asList(stationArray);
|
||||
this.transferLine1 = null;
|
||||
this.transferLine2 = null;
|
||||
}
|
||||
Line(boolean directionMayInvert, Station... stationArray) {
|
||||
this.requiresTransfer = false;
|
||||
this.directionMayInvert = directionMayInvert;
|
||||
stations = Arrays.asList(stationArray);
|
||||
this.transferLine1 = null;
|
||||
this.transferLine2 = null;
|
||||
}
|
||||
|
||||
private Line(Line transferLine1, Line transferLine2,
|
||||
Station... stationArray) {
|
||||
this.requiresTransfer = true;
|
||||
this.directionMayInvert = false;
|
||||
stations = Arrays.asList(stationArray);
|
||||
this.transferLine1 = transferLine1;
|
||||
this.transferLine2 = transferLine2;
|
||||
}
|
||||
Line(Line transferLine1, Line transferLine2,
|
||||
Station... stationArray) {
|
||||
this.requiresTransfer = true;
|
||||
this.directionMayInvert = false;
|
||||
stations = Arrays.asList(stationArray);
|
||||
this.transferLine1 = transferLine1;
|
||||
this.transferLine2 = transferLine2;
|
||||
}
|
||||
|
||||
private Line(boolean directionMayInvert, Line transferLine1,
|
||||
Line transferLine2, Station... stationArray) {
|
||||
this.requiresTransfer = true;
|
||||
this.directionMayInvert = directionMayInvert;
|
||||
stations = Arrays.asList(stationArray);
|
||||
this.transferLine1 = transferLine1;
|
||||
this.transferLine2 = transferLine2;
|
||||
}
|
||||
Line(boolean directionMayInvert, Line transferLine1,
|
||||
Line transferLine2, Station... stationArray) {
|
||||
this.requiresTransfer = true;
|
||||
this.directionMayInvert = directionMayInvert;
|
||||
stations = Arrays.asList(stationArray);
|
||||
this.transferLine1 = transferLine1;
|
||||
this.transferLine2 = transferLine2;
|
||||
}
|
||||
|
||||
public static Collection<Line> getLinesForStation(Station station) {
|
||||
Collection<Line> lines = new ArrayList<Line>();
|
||||
for (Line line : Line.values()) {
|
||||
if (line.stations.contains(station)) {
|
||||
lines.add(line);
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
public static Collection<Line> getLinesForStation(Station station) {
|
||||
Collection<Line> lines = new ArrayList<Line>();
|
||||
for (Line line : Line.values()) {
|
||||
if (line.stations.contains(station)) {
|
||||
lines.add(line);
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
public static Collection<Line> getLinesWithStations(Station station1,
|
||||
Station station2) {
|
||||
Collection<Line> lines = new ArrayList<Line>();
|
||||
for (Line line : Line.values()) {
|
||||
if (line.stations.contains(station1)
|
||||
&& line.stations.contains(station2)) {
|
||||
lines.add(line);
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
public static Collection<Line> getLinesWithStations(Station station1,
|
||||
Station station2) {
|
||||
Collection<Line> lines = new ArrayList<Line>();
|
||||
for (Line line : Line.values()) {
|
||||
if (line.stations.contains(station1)
|
||||
&& line.stations.contains(station2)) {
|
||||
lines.add(line);
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
public static Set<Station> getPotentialDestinations(Station station) {
|
||||
Set<Station> destinations = new TreeSet<Station>();
|
||||
public static Set<Station> getPotentialDestinations(Station station) {
|
||||
Set<Station> destinations = new TreeSet<Station>();
|
||||
|
||||
for (Line line : getLinesForStation(station)) {
|
||||
destinations.addAll(line.stations);
|
||||
}
|
||||
for (Line line : getLinesForStation(station)) {
|
||||
destinations.addAll(line.stations);
|
||||
}
|
||||
|
||||
destinations.remove(station);
|
||||
destinations.remove(station);
|
||||
|
||||
return destinations;
|
||||
}
|
||||
return destinations;
|
||||
}
|
||||
}
|
||||
|
@ -6,147 +6,147 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class RealTimeDepartures {
|
||||
public RealTimeDepartures(Station origin, Station destination,
|
||||
List<Route> routes) {
|
||||
this.origin = origin;
|
||||
this.destination = destination;
|
||||
this.routes = routes;
|
||||
this.unfilteredDepartures = new ArrayList<Departure>();
|
||||
}
|
||||
public RealTimeDepartures(Station origin, Station destination,
|
||||
List<Route> routes) {
|
||||
this.origin = origin;
|
||||
this.destination = destination;
|
||||
this.routes = routes;
|
||||
this.unfilteredDepartures = new ArrayList<Departure>();
|
||||
}
|
||||
|
||||
private Station origin;
|
||||
private Station destination;
|
||||
private long time;
|
||||
private Station origin;
|
||||
private Station destination;
|
||||
private long time;
|
||||
|
||||
private List<Departure> departures;
|
||||
private List<Departure> departures;
|
||||
|
||||
final private List<Departure> unfilteredDepartures;
|
||||
final private List<Departure> unfilteredDepartures;
|
||||
|
||||
private List<Route> routes;
|
||||
private List<Route> routes;
|
||||
|
||||
public Station getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
public Station getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
public void setOrigin(Station origin) {
|
||||
this.origin = origin;
|
||||
}
|
||||
public void setOrigin(Station origin) {
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
public Station getDestination() {
|
||||
return destination;
|
||||
}
|
||||
public Station getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
public void setDestination(Station destination) {
|
||||
this.destination = destination;
|
||||
}
|
||||
public void setDestination(Station destination) {
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(long time) {
|
||||
this.time = time;
|
||||
}
|
||||
public void setTime(long time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public List<Departure> getDepartures() {
|
||||
if (departures == null) {
|
||||
departures = new ArrayList<Departure>();
|
||||
}
|
||||
return departures;
|
||||
}
|
||||
public List<Departure> getDepartures() {
|
||||
if (departures == null) {
|
||||
departures = new ArrayList<Departure>();
|
||||
}
|
||||
return departures;
|
||||
}
|
||||
|
||||
public void setDepartures(List<Departure> departures) {
|
||||
this.departures = departures;
|
||||
}
|
||||
public void setDepartures(List<Departure> departures) {
|
||||
this.departures = departures;
|
||||
}
|
||||
|
||||
public void includeTransferRoutes() {
|
||||
routes.addAll(origin.getTransferRoutes(destination));
|
||||
rebuildFilteredDepaturesCollection();
|
||||
}
|
||||
public void includeTransferRoutes() {
|
||||
routes.addAll(origin.getTransferRoutes(destination));
|
||||
rebuildFilteredDepaturesCollection();
|
||||
}
|
||||
|
||||
public void includeDoubleTransferRoutes() {
|
||||
routes.addAll(origin.getDoubleTransferRoutes(destination));
|
||||
rebuildFilteredDepaturesCollection();
|
||||
}
|
||||
public void includeDoubleTransferRoutes() {
|
||||
routes.addAll(origin.getDoubleTransferRoutes(destination));
|
||||
rebuildFilteredDepaturesCollection();
|
||||
}
|
||||
|
||||
private void rebuildFilteredDepaturesCollection() {
|
||||
getDepartures().clear();
|
||||
for (Departure departure : unfilteredDepartures) {
|
||||
addDepartureIfApplicable(departure);
|
||||
}
|
||||
}
|
||||
private void rebuildFilteredDepaturesCollection() {
|
||||
getDepartures().clear();
|
||||
for (Departure departure : unfilteredDepartures) {
|
||||
addDepartureIfApplicable(departure);
|
||||
}
|
||||
}
|
||||
|
||||
public void addDeparture(Departure departure) {
|
||||
unfilteredDepartures.add(departure);
|
||||
addDepartureIfApplicable(departure);
|
||||
}
|
||||
public void addDeparture(Departure departure) {
|
||||
unfilteredDepartures.add(departure);
|
||||
addDepartureIfApplicable(departure);
|
||||
}
|
||||
|
||||
private void addDepartureIfApplicable(Departure departure) {
|
||||
Station destination = Station.getByAbbreviation(departure
|
||||
.getTrainDestinationAbbreviation());
|
||||
if (departure.getLine() == null)
|
||||
return;
|
||||
for (Route route : routes) {
|
||||
if (route.trainDestinationIsApplicable(destination,
|
||||
departure.getLine())) {
|
||||
departure.setRequiresTransfer(route.hasTransfer());
|
||||
departure
|
||||
.setTransferScheduled(Line.YELLOW_ORANGE_SCHEDULED_TRANSFER
|
||||
.equals(route.getDirectLine()));
|
||||
getDepartures().add(departure);
|
||||
departure.calculateEstimates(time);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void addDepartureIfApplicable(Departure departure) {
|
||||
Station destination = Station.getByAbbreviation(departure
|
||||
.getTrainDestinationAbbreviation());
|
||||
if (departure.getLine() == null)
|
||||
return;
|
||||
for (Route route : routes) {
|
||||
if (route.trainDestinationIsApplicable(destination,
|
||||
departure.getLine())) {
|
||||
departure.setRequiresTransfer(route.hasTransfer());
|
||||
departure
|
||||
.setTransferScheduled(Line.YELLOW_ORANGE_SCHEDULED_TRANSFER
|
||||
.equals(route.getDirectLine()));
|
||||
getDepartures().add(departure);
|
||||
departure.calculateEstimates(time);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void sortDepartures() {
|
||||
Collections.sort(getDepartures());
|
||||
}
|
||||
public void sortDepartures() {
|
||||
Collections.sort(getDepartures());
|
||||
}
|
||||
|
||||
public void finalizeDeparturesList() {
|
||||
boolean hasDirectRoute = false;
|
||||
for (Departure departure : getDepartures()) {
|
||||
if (!departure.getRequiresTransfer()) {
|
||||
hasDirectRoute = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasDirectRoute) {
|
||||
Iterator<Departure> iterator = getDepartures().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Departure departure = iterator.next();
|
||||
if (departure.getRequiresTransfer()
|
||||
&& (!departure.isTransferScheduled() || departure
|
||||
.getTrainDestination().isBetween(getOrigin(),
|
||||
getDestination(), departure.getLine()))) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
sortDepartures();
|
||||
}
|
||||
public void finalizeDeparturesList() {
|
||||
boolean hasDirectRoute = false;
|
||||
for (Departure departure : getDepartures()) {
|
||||
if (!departure.getRequiresTransfer()) {
|
||||
hasDirectRoute = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasDirectRoute) {
|
||||
Iterator<Departure> iterator = getDepartures().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Departure departure = iterator.next();
|
||||
if (departure.getRequiresTransfer()
|
||||
&& (!departure.isTransferScheduled() || departure
|
||||
.getTrainDestination().isBetween(getOrigin(),
|
||||
getDestination(), departure.getLine()))) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
sortDepartures();
|
||||
}
|
||||
|
||||
public List<Route> getRoutes() {
|
||||
return routes;
|
||||
}
|
||||
public List<Route> getRoutes() {
|
||||
return routes;
|
||||
}
|
||||
|
||||
public void setRoutes(List<Route> routes) {
|
||||
this.routes = routes;
|
||||
}
|
||||
public void setRoutes(List<Route> routes) {
|
||||
this.routes = routes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("RealTimeDepartures [origin=");
|
||||
builder.append(origin);
|
||||
builder.append(", destination=");
|
||||
builder.append(destination);
|
||||
builder.append(", time=");
|
||||
builder.append(time);
|
||||
builder.append(", departures=");
|
||||
builder.append(departures);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("RealTimeDepartures [origin=");
|
||||
builder.append(origin);
|
||||
builder.append(", destination=");
|
||||
builder.append(destination);
|
||||
builder.append(", time=");
|
||||
builder.append(time);
|
||||
builder.append(", departures=");
|
||||
builder.append(departures);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
@ -3,109 +3,109 @@ package com.dougkeen.bart.model;
|
||||
import java.util.Collection;
|
||||
|
||||
public class Route {
|
||||
private Station origin;
|
||||
private Station destination;
|
||||
private Line directLine;
|
||||
private Collection<Line> transferLines;
|
||||
private boolean requiresTransfer;
|
||||
private Station transferStation;
|
||||
private String direction;
|
||||
private Station origin;
|
||||
private Station destination;
|
||||
private Line directLine;
|
||||
private Collection<Line> transferLines;
|
||||
private boolean requiresTransfer;
|
||||
private Station transferStation;
|
||||
private String direction;
|
||||
|
||||
public Station getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
public Station getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
public void setOrigin(Station origin) {
|
||||
this.origin = origin;
|
||||
}
|
||||
public void setOrigin(Station origin) {
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
public Station getDestination() {
|
||||
return destination;
|
||||
}
|
||||
public Station getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
public void setDestination(Station destination) {
|
||||
this.destination = destination;
|
||||
}
|
||||
public void setDestination(Station destination) {
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
public Line getDirectLine() {
|
||||
return directLine;
|
||||
}
|
||||
public Line getDirectLine() {
|
||||
return directLine;
|
||||
}
|
||||
|
||||
public void setDirectLine(Line line) {
|
||||
this.directLine = line;
|
||||
}
|
||||
public void setDirectLine(Line line) {
|
||||
this.directLine = line;
|
||||
}
|
||||
|
||||
public Collection<Line> getTransferLines() {
|
||||
return transferLines;
|
||||
}
|
||||
public Collection<Line> getTransferLines() {
|
||||
return transferLines;
|
||||
}
|
||||
|
||||
public void setTransferLines(Collection<Line> transferLines) {
|
||||
this.transferLines = transferLines;
|
||||
}
|
||||
public void setTransferLines(Collection<Line> transferLines) {
|
||||
this.transferLines = transferLines;
|
||||
}
|
||||
|
||||
public boolean hasTransfer() {
|
||||
return requiresTransfer;
|
||||
}
|
||||
public boolean hasTransfer() {
|
||||
return requiresTransfer;
|
||||
}
|
||||
|
||||
public void setTransfer(boolean requiresTransfer) {
|
||||
this.requiresTransfer = requiresTransfer;
|
||||
}
|
||||
public void setTransfer(boolean requiresTransfer) {
|
||||
this.requiresTransfer = requiresTransfer;
|
||||
}
|
||||
|
||||
public Station getTransferStation() {
|
||||
return transferStation;
|
||||
}
|
||||
public Station getTransferStation() {
|
||||
return transferStation;
|
||||
}
|
||||
|
||||
public void setTransferStation(Station transferStation) {
|
||||
this.transferStation = transferStation;
|
||||
}
|
||||
public void setTransferStation(Station transferStation) {
|
||||
this.transferStation = transferStation;
|
||||
}
|
||||
|
||||
public String getDirection() {
|
||||
return direction;
|
||||
}
|
||||
public String getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
public void setDirection(String direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
public void setDirection(String direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("Route [origin=");
|
||||
builder.append(origin);
|
||||
builder.append(", destination=");
|
||||
builder.append(destination);
|
||||
builder.append(", line=");
|
||||
builder.append(directLine);
|
||||
builder.append(", requiresTransfer=");
|
||||
builder.append(requiresTransfer);
|
||||
builder.append(", transferStation=");
|
||||
builder.append(transferStation);
|
||||
builder.append(", direction=");
|
||||
builder.append(direction);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("Route [origin=");
|
||||
builder.append(origin);
|
||||
builder.append(", destination=");
|
||||
builder.append(destination);
|
||||
builder.append(", line=");
|
||||
builder.append(directLine);
|
||||
builder.append(", requiresTransfer=");
|
||||
builder.append(requiresTransfer);
|
||||
builder.append(", transferStation=");
|
||||
builder.append(transferStation);
|
||||
builder.append(", direction=");
|
||||
builder.append(direction);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public boolean trainDestinationIsApplicable(Station lineDestination,
|
||||
Line viaLine) {
|
||||
Line routeLine = getDirectLine();
|
||||
if (routeLine.transferLine1 != null
|
||||
&& viaLine.equals(routeLine.transferLine1)) {
|
||||
return true;
|
||||
} else if (routeLine.transferLine2 != null
|
||||
&& viaLine.equals(routeLine.transferLine2)) {
|
||||
return true;
|
||||
} else if (requiresTransfer && transferLines != null
|
||||
&& !transferLines.isEmpty()) {
|
||||
return transferLines.contains(viaLine);
|
||||
} else {
|
||||
int originIndex = viaLine.stations.indexOf(origin);
|
||||
int routeDestinationIndex = viaLine.stations.indexOf(destination);
|
||||
int lineDestinationIndex = viaLine.stations
|
||||
.indexOf(lineDestination);
|
||||
return routeDestinationIndex >= 0
|
||||
&& ((originIndex <= routeDestinationIndex && routeDestinationIndex <= lineDestinationIndex) || (originIndex >= routeDestinationIndex && routeDestinationIndex >= lineDestinationIndex));
|
||||
}
|
||||
}
|
||||
public boolean trainDestinationIsApplicable(Station lineDestination,
|
||||
Line viaLine) {
|
||||
Line routeLine = getDirectLine();
|
||||
if (routeLine.transferLine1 != null
|
||||
&& viaLine.equals(routeLine.transferLine1)) {
|
||||
return true;
|
||||
} else if (routeLine.transferLine2 != null
|
||||
&& viaLine.equals(routeLine.transferLine2)) {
|
||||
return true;
|
||||
} else if (requiresTransfer && transferLines != null
|
||||
&& !transferLines.isEmpty()) {
|
||||
return transferLines.contains(viaLine);
|
||||
} else {
|
||||
int originIndex = viaLine.stations.indexOf(origin);
|
||||
int routeDestinationIndex = viaLine.stations.indexOf(destination);
|
||||
int lineDestinationIndex = viaLine.stations
|
||||
.indexOf(lineDestination);
|
||||
return routeDestinationIndex >= 0
|
||||
&& ((originIndex <= routeDestinationIndex && routeDestinationIndex <= lineDestinationIndex) || (originIndex >= routeDestinationIndex && routeDestinationIndex >= lineDestinationIndex));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,85 +5,85 @@ import java.util.List;
|
||||
|
||||
public class ScheduleInformation {
|
||||
|
||||
public ScheduleInformation(Station origin, Station destination) {
|
||||
super();
|
||||
this.origin = origin;
|
||||
this.destination = destination;
|
||||
}
|
||||
public ScheduleInformation(Station origin, Station destination) {
|
||||
super();
|
||||
this.origin = origin;
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
private Station origin;
|
||||
private Station destination;
|
||||
private long date;
|
||||
private List<ScheduleItem> trips;
|
||||
private Station origin;
|
||||
private Station destination;
|
||||
private long date;
|
||||
private List<ScheduleItem> trips;
|
||||
|
||||
public Station getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
public Station getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
public void setOrigin(Station origin) {
|
||||
this.origin = origin;
|
||||
}
|
||||
public void setOrigin(Station origin) {
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
public Station getDestination() {
|
||||
return destination;
|
||||
}
|
||||
public Station getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
public void setDestination(Station destination) {
|
||||
this.destination = destination;
|
||||
}
|
||||
public void setDestination(Station destination) {
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
public long getDate() {
|
||||
return date;
|
||||
}
|
||||
public long getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(long date) {
|
||||
this.date = date;
|
||||
}
|
||||
public void setDate(long date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public List<ScheduleItem> getTrips() {
|
||||
if (trips == null) {
|
||||
trips = new ArrayList<ScheduleItem>();
|
||||
}
|
||||
return trips;
|
||||
}
|
||||
public List<ScheduleItem> getTrips() {
|
||||
if (trips == null) {
|
||||
trips = new ArrayList<ScheduleItem>();
|
||||
}
|
||||
return trips;
|
||||
}
|
||||
|
||||
public void setTrips(List<ScheduleItem> trips) {
|
||||
this.trips = trips;
|
||||
}
|
||||
public void setTrips(List<ScheduleItem> trips) {
|
||||
this.trips = trips;
|
||||
}
|
||||
|
||||
public void addTrip(ScheduleItem trip) {
|
||||
getTrips().add(trip);
|
||||
}
|
||||
public void addTrip(ScheduleItem trip) {
|
||||
getTrips().add(trip);
|
||||
}
|
||||
|
||||
public long getLatestDepartureTime() {
|
||||
if (getTrips().isEmpty())
|
||||
return -1;
|
||||
else
|
||||
return getTrips().get(getTrips().size() - 1).getDepartureTime();
|
||||
}
|
||||
public long getLatestDepartureTime() {
|
||||
if (getTrips().isEmpty())
|
||||
return -1;
|
||||
else
|
||||
return getTrips().get(getTrips().size() - 1).getDepartureTime();
|
||||
}
|
||||
|
||||
private int aveTripLength = -1;
|
||||
private int tripCount = 0;
|
||||
private int aveTripLength = -1;
|
||||
private int tripCount = 0;
|
||||
|
||||
public int getAverageTripLength() {
|
||||
if (aveTripLength < 0) {
|
||||
int sum = 0;
|
||||
for (ScheduleItem trip : getTrips()) {
|
||||
int tripLength = trip.getTripLength();
|
||||
if (tripLength > 0) {
|
||||
sum += tripLength;
|
||||
tripCount++;
|
||||
}
|
||||
}
|
||||
if (tripCount > 0) {
|
||||
aveTripLength = sum / tripCount;
|
||||
}
|
||||
}
|
||||
return aveTripLength;
|
||||
}
|
||||
public int getAverageTripLength() {
|
||||
if (aveTripLength < 0) {
|
||||
int sum = 0;
|
||||
for (ScheduleItem trip : getTrips()) {
|
||||
int tripLength = trip.getTripLength();
|
||||
if (tripLength > 0) {
|
||||
sum += tripLength;
|
||||
tripCount++;
|
||||
}
|
||||
}
|
||||
if (tripCount > 0) {
|
||||
aveTripLength = sum / tripCount;
|
||||
}
|
||||
}
|
||||
return aveTripLength;
|
||||
}
|
||||
|
||||
public int getTripCountForAverage() {
|
||||
getAverageTripLength();
|
||||
return tripCount;
|
||||
}
|
||||
public int getTripCountForAverage() {
|
||||
getAverageTripLength();
|
||||
return tripCount;
|
||||
}
|
||||
}
|
@ -6,110 +6,110 @@ import java.util.Date;
|
||||
|
||||
public class ScheduleItem {
|
||||
|
||||
public ScheduleItem() {
|
||||
super();
|
||||
}
|
||||
public ScheduleItem() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ScheduleItem(Station origin, Station destination) {
|
||||
super();
|
||||
this.origin = origin;
|
||||
this.destination = destination;
|
||||
}
|
||||
public ScheduleItem(Station origin, Station destination) {
|
||||
super();
|
||||
this.origin = origin;
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
public static final int SCHEDULE_ITEM_DEPARTURE_EQUALS_TOLERANCE = 120000;
|
||||
public static final int SCHEDULE_ITEM_DEPARTURE_EQUALS_TOLERANCE = 120000;
|
||||
|
||||
private Station origin;
|
||||
private Station destination;
|
||||
private String fare;
|
||||
private long departureTime;
|
||||
private long arrivalTime;
|
||||
private boolean bikesAllowed;
|
||||
private String trainHeadStation;
|
||||
private Station origin;
|
||||
private Station destination;
|
||||
private String fare;
|
||||
private long departureTime;
|
||||
private long arrivalTime;
|
||||
private boolean bikesAllowed;
|
||||
private String trainHeadStation;
|
||||
|
||||
public Station getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
public Station getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
public void setOrigin(Station origin) {
|
||||
this.origin = origin;
|
||||
}
|
||||
public void setOrigin(Station origin) {
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
public Station getDestination() {
|
||||
return destination;
|
||||
}
|
||||
public Station getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
public void setDestination(Station destination) {
|
||||
this.destination = destination;
|
||||
}
|
||||
public void setDestination(Station destination) {
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
public String getFare() {
|
||||
return fare;
|
||||
}
|
||||
public String getFare() {
|
||||
return fare;
|
||||
}
|
||||
|
||||
public void setFare(String fare) {
|
||||
this.fare = fare;
|
||||
}
|
||||
public void setFare(String fare) {
|
||||
this.fare = fare;
|
||||
}
|
||||
|
||||
public long getDepartureTime() {
|
||||
return departureTime;
|
||||
}
|
||||
public long getDepartureTime() {
|
||||
return departureTime;
|
||||
}
|
||||
|
||||
public void setDepartureTime(long departureTime) {
|
||||
this.departureTime = departureTime;
|
||||
}
|
||||
public void setDepartureTime(long departureTime) {
|
||||
this.departureTime = departureTime;
|
||||
}
|
||||
|
||||
public long getArrivalTime() {
|
||||
return arrivalTime;
|
||||
}
|
||||
public long getArrivalTime() {
|
||||
return arrivalTime;
|
||||
}
|
||||
|
||||
public void setArrivalTime(long arrivalTime) {
|
||||
this.arrivalTime = arrivalTime;
|
||||
}
|
||||
public void setArrivalTime(long arrivalTime) {
|
||||
this.arrivalTime = arrivalTime;
|
||||
}
|
||||
|
||||
public int getTripLength() {
|
||||
if (departureTime <= 0 || arrivalTime <= 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return (int) (arrivalTime - departureTime);
|
||||
}
|
||||
}
|
||||
public int getTripLength() {
|
||||
if (departureTime <= 0 || arrivalTime <= 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return (int) (arrivalTime - departureTime);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isBikesAllowed() {
|
||||
return bikesAllowed;
|
||||
}
|
||||
public boolean isBikesAllowed() {
|
||||
return bikesAllowed;
|
||||
}
|
||||
|
||||
public void setBikesAllowed(boolean bikesAllowed) {
|
||||
this.bikesAllowed = bikesAllowed;
|
||||
}
|
||||
public void setBikesAllowed(boolean bikesAllowed) {
|
||||
this.bikesAllowed = bikesAllowed;
|
||||
}
|
||||
|
||||
public String getTrainHeadStation() {
|
||||
return trainHeadStation;
|
||||
}
|
||||
public String getTrainHeadStation() {
|
||||
return trainHeadStation;
|
||||
}
|
||||
|
||||
public void setTrainHeadStation(String trainHeadStation) {
|
||||
this.trainHeadStation = trainHeadStation;
|
||||
}
|
||||
public void setTrainHeadStation(String trainHeadStation) {
|
||||
this.trainHeadStation = trainHeadStation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
DateFormat format = SimpleDateFormat.getTimeInstance();
|
||||
builder.append("ScheduleItem [origin=");
|
||||
builder.append(origin);
|
||||
builder.append(", destination=");
|
||||
builder.append(destination);
|
||||
builder.append(", fare=");
|
||||
builder.append(fare);
|
||||
builder.append(", departureTime=");
|
||||
builder.append(format.format(new Date(departureTime)));
|
||||
builder.append(", arrivalTime=");
|
||||
builder.append(format.format(new Date(arrivalTime)));
|
||||
builder.append(", bikesAllowed=");
|
||||
builder.append(bikesAllowed);
|
||||
builder.append(", trainHeadStation=");
|
||||
builder.append(trainHeadStation);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
DateFormat format = SimpleDateFormat.getTimeInstance();
|
||||
builder.append("ScheduleItem [origin=");
|
||||
builder.append(origin);
|
||||
builder.append(", destination=");
|
||||
builder.append(destination);
|
||||
builder.append(", fare=");
|
||||
builder.append(fare);
|
||||
builder.append(", departureTime=");
|
||||
builder.append(format.format(new Date(departureTime)));
|
||||
builder.append(", arrivalTime=");
|
||||
builder.append(format.format(new Date(arrivalTime)));
|
||||
builder.append(", bikesAllowed=");
|
||||
builder.append(bikesAllowed);
|
||||
builder.append(", trainHeadStation=");
|
||||
builder.append(trainHeadStation);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,280 +7,280 @@ import java.util.List;
|
||||
import android.util.Log;
|
||||
|
||||
public enum Station {
|
||||
_12TH("12th", "12th St./Oakland City Center", "12th St Oak", false, false,
|
||||
"bayf", "bayf"),
|
||||
_16TH("16th", "16th St. Mission", "16th St", false, false),
|
||||
_19TH("19th", "19th St./Oakland", "19th St Oak", false, false, "bayf",
|
||||
"bayf"),
|
||||
_24TH("24th", "24th St. Mission", "24th St", false, false),
|
||||
ASHB("ashb", "Ashby", "Ashby", false, false, "mcar", "mcar"),
|
||||
BALB("balb", "Balboa Park", "Balboa", false, false),
|
||||
BAYF("bayf", "Bay Fair", "Bay Fair", true, false, "mcar", "mcar"),
|
||||
CAST("cast", "Castro Valley", "Castro Vly", false, false, "bayf", "bayf"),
|
||||
CIVC("civc", "Civic Center", "Civic Ctr", false, false),
|
||||
COLS("cols", "Coliseum/Oakland Airport", "Coliseum/OAK", true, false,
|
||||
"mcar", "mcar"),
|
||||
COLM("colm", "Colma", "Colma", false, false, "balb", "balb"),
|
||||
CONC("conc", "Concord", "Concord", false, false, "mcar", "mcar"),
|
||||
DALY("daly", "Daly City", "Daly City", false, false),
|
||||
DBRK("dbrk", "Downtown Berkeley", "Dtwn Berk", false, false, "mcar", "mcar"),
|
||||
DUBL("dubl", "Dublin/Pleasanton", "Dbln/Plsntn", false, true, "bayf",
|
||||
"bayf", true, 719999),
|
||||
DELN("deln", "El Cerrito del Norte", "El Cer/Norte", false, false, "mcar",
|
||||
"mcar"),
|
||||
PLZA("plza", "El Cerrito Plaza", "El Cer/Plz", false, false, "mcar", "mcar"),
|
||||
EMBR("embr", "Embarcadero", "Embarcdro", false, false),
|
||||
FRMT("frmt", "Fremont", "Fremont", true, true, "bayf", "bayf", true, 299999),
|
||||
FTVL("ftvl", "Fruitvale", "Fruitvale", true, false, "mcar", "mcar"),
|
||||
GLEN("glen", "Glen Park", "Glen Park", false, false),
|
||||
HAYW("hayw", "Hayward", "Hayward", true, false, "bayf", "bayf"),
|
||||
LAFY("lafy", "Lafayette", "Lafayette", false, false, "mcar", "mcar"),
|
||||
LAKE("lake", "Lake Merritt", "Lk Merritt", true, false, "mcar", "mcar"),
|
||||
MCAR("mcar", "MacArthur", "MacArthur", false, false, "bayf", "bayf"),
|
||||
MLBR("mlbr", "Millbrae", "Millbrae", false, true, "balb", "balb", true,
|
||||
719999),
|
||||
MONT("mont", "Montgomery St.", "Montgomery", false, false),
|
||||
NBRK("nbrk", "North Berkeley", "N Berkeley", false, false, "mcar", "mcar"),
|
||||
NCON("ncon", "North Concord/Martinez", "N Conc/Mrtnz", false, false,
|
||||
"mcar", "mcar"),
|
||||
ORIN("orin", "Orinda", "Orinda", false, false, "mcar", "mcar"),
|
||||
PITT("pitt", "Pittsburg/Bay Point", "Pitt/Bay Pt", false, true, "mcar",
|
||||
"mcar", true, 719999),
|
||||
PHIL("phil", "Pleasant Hill", "Plsnt Hill", false, false, "mcar", "mcar"),
|
||||
POWL("powl", "Powell St.", "Powell", false, false),
|
||||
RICH("rich", "Richmond", "Richmond", false, true, "mcar", "mcar", true,
|
||||
299999),
|
||||
ROCK("rock", "Rockridge", "Rockridge", false, false, "mcar", "mcar"),
|
||||
SBRN("sbrn", "San Bruno", "San Bruno", false, false, "balb", "balb"),
|
||||
SANL("sanl", "San Leandro", "San Leandro", true, false, "mcar", "mcar"),
|
||||
SFIA("sfia", "SFO Airport", "SFO", false, false, "balb", "balb", true,
|
||||
719999),
|
||||
SHAY("shay", "South Hayward", "S Hayward", true, false, "bayf", "bayf"),
|
||||
SSAN("ssan", "South San Francisco", "S San Fran", false, false, "balb",
|
||||
"balb"),
|
||||
UCTY("ucty", "Union City", "Union City", true, false, "bayf", "bayf"),
|
||||
WCRK("wcrk", "Walnut Creek", "Walnut Crk", false, false, "mcar", "mcar"),
|
||||
WDUB("wdub", "West Dublin/Pleasanton", "W Dbln/Plsntn", false, false,
|
||||
"bayf", "bayf"),
|
||||
WOAK("woak", "West Oakland", "W Oakland", false, false),
|
||||
SPCL("spcl", "Special", "Special", false, false);
|
||||
_12TH("12th", "12th St./Oakland City Center", "12th St Oak", false, false,
|
||||
"bayf", "bayf"),
|
||||
_16TH("16th", "16th St. Mission", "16th St", false, false),
|
||||
_19TH("19th", "19th St./Oakland", "19th St Oak", false, false, "bayf",
|
||||
"bayf"),
|
||||
_24TH("24th", "24th St. Mission", "24th St", false, false),
|
||||
ASHB("ashb", "Ashby", "Ashby", false, false, "mcar", "mcar"),
|
||||
BALB("balb", "Balboa Park", "Balboa", false, false),
|
||||
BAYF("bayf", "Bay Fair", "Bay Fair", true, false, "mcar", "mcar"),
|
||||
CAST("cast", "Castro Valley", "Castro Vly", false, false, "bayf", "bayf"),
|
||||
CIVC("civc", "Civic Center", "Civic Ctr", false, false),
|
||||
COLS("cols", "Coliseum/Oakland Airport", "Coliseum/OAK", true, false,
|
||||
"mcar", "mcar"),
|
||||
COLM("colm", "Colma", "Colma", false, false, "balb", "balb"),
|
||||
CONC("conc", "Concord", "Concord", false, false, "mcar", "mcar"),
|
||||
DALY("daly", "Daly City", "Daly City", false, false),
|
||||
DBRK("dbrk", "Downtown Berkeley", "Dtwn Berk", false, false, "mcar", "mcar"),
|
||||
DUBL("dubl", "Dublin/Pleasanton", "Dbln/Plsntn", false, true, "bayf",
|
||||
"bayf", true, 719999),
|
||||
DELN("deln", "El Cerrito del Norte", "El Cer/Norte", false, false, "mcar",
|
||||
"mcar"),
|
||||
PLZA("plza", "El Cerrito Plaza", "El Cer/Plz", false, false, "mcar", "mcar"),
|
||||
EMBR("embr", "Embarcadero", "Embarcdro", false, false),
|
||||
FRMT("frmt", "Fremont", "Fremont", true, true, "bayf", "bayf", true, 299999),
|
||||
FTVL("ftvl", "Fruitvale", "Fruitvale", true, false, "mcar", "mcar"),
|
||||
GLEN("glen", "Glen Park", "Glen Park", false, false),
|
||||
HAYW("hayw", "Hayward", "Hayward", true, false, "bayf", "bayf"),
|
||||
LAFY("lafy", "Lafayette", "Lafayette", false, false, "mcar", "mcar"),
|
||||
LAKE("lake", "Lake Merritt", "Lk Merritt", true, false, "mcar", "mcar"),
|
||||
MCAR("mcar", "MacArthur", "MacArthur", false, false, "bayf", "bayf"),
|
||||
MLBR("mlbr", "Millbrae", "Millbrae", false, true, "balb", "balb", true,
|
||||
719999),
|
||||
MONT("mont", "Montgomery St.", "Montgomery", false, false),
|
||||
NBRK("nbrk", "North Berkeley", "N Berkeley", false, false, "mcar", "mcar"),
|
||||
NCON("ncon", "North Concord/Martinez", "N Conc/Mrtnz", false, false,
|
||||
"mcar", "mcar"),
|
||||
ORIN("orin", "Orinda", "Orinda", false, false, "mcar", "mcar"),
|
||||
PITT("pitt", "Pittsburg/Bay Point", "Pitt/Bay Pt", false, true, "mcar",
|
||||
"mcar", true, 719999),
|
||||
PHIL("phil", "Pleasant Hill", "Plsnt Hill", false, false, "mcar", "mcar"),
|
||||
POWL("powl", "Powell St.", "Powell", false, false),
|
||||
RICH("rich", "Richmond", "Richmond", false, true, "mcar", "mcar", true,
|
||||
299999),
|
||||
ROCK("rock", "Rockridge", "Rockridge", false, false, "mcar", "mcar"),
|
||||
SBRN("sbrn", "San Bruno", "San Bruno", false, false, "balb", "balb"),
|
||||
SANL("sanl", "San Leandro", "San Leandro", true, false, "mcar", "mcar"),
|
||||
SFIA("sfia", "SFO Airport", "SFO", false, false, "balb", "balb", true,
|
||||
719999),
|
||||
SHAY("shay", "South Hayward", "S Hayward", true, false, "bayf", "bayf"),
|
||||
SSAN("ssan", "South San Francisco", "S San Fran", false, false, "balb",
|
||||
"balb"),
|
||||
UCTY("ucty", "Union City", "Union City", true, false, "bayf", "bayf"),
|
||||
WCRK("wcrk", "Walnut Creek", "Walnut Crk", false, false, "mcar", "mcar"),
|
||||
WDUB("wdub", "West Dublin/Pleasanton", "W Dbln/Plsntn", false, false,
|
||||
"bayf", "bayf"),
|
||||
WOAK("woak", "West Oakland", "W Oakland", false, false),
|
||||
SPCL("spcl", "Special", "Special", false, false);
|
||||
|
||||
public final String abbreviation;
|
||||
public final String name;
|
||||
public final String shortName;
|
||||
public final boolean transferFriendly;
|
||||
public final boolean invertDirection;
|
||||
protected final String inboundTransferStation;
|
||||
protected final String outboundTransferStation;
|
||||
public final boolean endOfLine;
|
||||
public final boolean longStationLinger;
|
||||
public final int departureEqualityTolerance;
|
||||
public final String abbreviation;
|
||||
public final String name;
|
||||
public final String shortName;
|
||||
public final boolean transferFriendly;
|
||||
public final boolean invertDirection;
|
||||
protected final String inboundTransferStation;
|
||||
protected final String outboundTransferStation;
|
||||
public final boolean endOfLine;
|
||||
public final boolean longStationLinger;
|
||||
public final int departureEqualityTolerance;
|
||||
|
||||
public final static int DEFAULT_DEPARTURE_EQUALITY_TOLERANCE = 119999;
|
||||
public final static int DEFAULT_DEPARTURE_EQUALITY_TOLERANCE = 119999;
|
||||
|
||||
private Station(String abbreviation, String name, String shortName,
|
||||
boolean invertDirection, boolean endOfLine) {
|
||||
this(abbreviation, name, shortName, invertDirection, endOfLine, null,
|
||||
null, false, DEFAULT_DEPARTURE_EQUALITY_TOLERANCE);
|
||||
}
|
||||
Station(String abbreviation, String name, String shortName,
|
||||
boolean invertDirection, boolean endOfLine) {
|
||||
this(abbreviation, name, shortName, invertDirection, endOfLine, null,
|
||||
null, false, DEFAULT_DEPARTURE_EQUALITY_TOLERANCE);
|
||||
}
|
||||
|
||||
private Station(String abbreviation, String name, String shortName,
|
||||
boolean invertDirection, boolean endOfLine, String transferStation) {
|
||||
this(abbreviation, name, shortName, invertDirection, endOfLine,
|
||||
transferStation, null, false,
|
||||
DEFAULT_DEPARTURE_EQUALITY_TOLERANCE);
|
||||
}
|
||||
Station(String abbreviation, String name, String shortName,
|
||||
boolean invertDirection, boolean endOfLine, String transferStation) {
|
||||
this(abbreviation, name, shortName, invertDirection, endOfLine,
|
||||
transferStation, null, false,
|
||||
DEFAULT_DEPARTURE_EQUALITY_TOLERANCE);
|
||||
}
|
||||
|
||||
private Station(String abbreviation, String name, String shortName,
|
||||
boolean invertDirection, boolean endOfLine,
|
||||
String inboundTransferStation, String outboundTransferStation) {
|
||||
this(abbreviation, name, shortName, invertDirection, endOfLine,
|
||||
inboundTransferStation, outboundTransferStation, false,
|
||||
DEFAULT_DEPARTURE_EQUALITY_TOLERANCE);
|
||||
}
|
||||
Station(String abbreviation, String name, String shortName,
|
||||
boolean invertDirection, boolean endOfLine,
|
||||
String inboundTransferStation, String outboundTransferStation) {
|
||||
this(abbreviation, name, shortName, invertDirection, endOfLine,
|
||||
inboundTransferStation, outboundTransferStation, false,
|
||||
DEFAULT_DEPARTURE_EQUALITY_TOLERANCE);
|
||||
}
|
||||
|
||||
private Station(String abbreviation, String name, String shortName,
|
||||
boolean invertDirection, boolean endOfLine,
|
||||
String inboundTransferStation, String outboundTransferStation,
|
||||
boolean longStationLinger, int departureEqualityTolerance) {
|
||||
this.abbreviation = abbreviation;
|
||||
this.name = name;
|
||||
this.shortName = shortName;
|
||||
this.invertDirection = invertDirection;
|
||||
this.inboundTransferStation = inboundTransferStation;
|
||||
this.transferFriendly = outboundTransferStation != null;
|
||||
this.outboundTransferStation = outboundTransferStation;
|
||||
this.endOfLine = endOfLine;
|
||||
this.longStationLinger = longStationLinger;
|
||||
this.departureEqualityTolerance = departureEqualityTolerance;
|
||||
}
|
||||
Station(String abbreviation, String name, String shortName,
|
||||
boolean invertDirection, boolean endOfLine,
|
||||
String inboundTransferStation, String outboundTransferStation,
|
||||
boolean longStationLinger, int departureEqualityTolerance) {
|
||||
this.abbreviation = abbreviation;
|
||||
this.name = name;
|
||||
this.shortName = shortName;
|
||||
this.invertDirection = invertDirection;
|
||||
this.inboundTransferStation = inboundTransferStation;
|
||||
this.transferFriendly = outboundTransferStation != null;
|
||||
this.outboundTransferStation = outboundTransferStation;
|
||||
this.endOfLine = endOfLine;
|
||||
this.longStationLinger = longStationLinger;
|
||||
this.departureEqualityTolerance = departureEqualityTolerance;
|
||||
}
|
||||
|
||||
public static Station getByAbbreviation(String abbr) {
|
||||
try {
|
||||
if (abbr == null) {
|
||||
return null;
|
||||
} else if (Character.isDigit(abbr.charAt(0))) {
|
||||
return Station.valueOf("_" + abbr.toUpperCase());
|
||||
} else {
|
||||
return Station.valueOf(abbr.toUpperCase());
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.e(Constants.TAG, "Could not find station for '" + abbr + "'", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public static Station getByAbbreviation(String abbr) {
|
||||
try {
|
||||
if (abbr == null) {
|
||||
return null;
|
||||
} else if (Character.isDigit(abbr.charAt(0))) {
|
||||
return Station.valueOf("_" + abbr.toUpperCase());
|
||||
} else {
|
||||
return Station.valueOf(abbr.toUpperCase());
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.e(Constants.TAG, "Could not find station for '" + abbr + "'", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Station getInboundTransferStation() {
|
||||
return getByAbbreviation(inboundTransferStation);
|
||||
}
|
||||
public Station getInboundTransferStation() {
|
||||
return getByAbbreviation(inboundTransferStation);
|
||||
}
|
||||
|
||||
public Station getOutboundTransferStation() {
|
||||
return getByAbbreviation(outboundTransferStation);
|
||||
}
|
||||
public Station getOutboundTransferStation() {
|
||||
return getByAbbreviation(outboundTransferStation);
|
||||
}
|
||||
|
||||
public boolean isValidEndpointForDestination(Station dest, Station endpoint) {
|
||||
for (Line line : Line.values()) {
|
||||
int origIndex = line.stations.indexOf(this);
|
||||
if (origIndex < 0)
|
||||
continue;
|
||||
int destIndex = line.stations.indexOf(dest);
|
||||
if (destIndex < 0)
|
||||
continue;
|
||||
int endpointIndex = line.stations.indexOf(endpoint);
|
||||
if (endpointIndex >= 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public boolean isValidEndpointForDestination(Station dest, Station endpoint) {
|
||||
for (Line line : Line.values()) {
|
||||
int origIndex = line.stations.indexOf(this);
|
||||
if (origIndex < 0)
|
||||
continue;
|
||||
int destIndex = line.stations.indexOf(dest);
|
||||
if (destIndex < 0)
|
||||
continue;
|
||||
int endpointIndex = line.stations.indexOf(endpoint);
|
||||
if (endpointIndex >= 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<Route> getDirectRoutesForDestination(Station dest) {
|
||||
return getDirectRoutesForDestination(this, dest, null, null);
|
||||
}
|
||||
public List<Route> getDirectRoutesForDestination(Station dest) {
|
||||
return getDirectRoutesForDestination(this, dest, null, null);
|
||||
}
|
||||
|
||||
public List<Route> getDirectRoutesForDestination(Station origin,
|
||||
Station dest, Station transferStation,
|
||||
Collection<Line> transferLines) {
|
||||
if (dest == null)
|
||||
return null;
|
||||
Boolean isNorth = null;
|
||||
List<Route> returnList = new ArrayList<Route>();
|
||||
final Collection<Line> applicableLines = Line.getLinesWithStations(
|
||||
this, dest);
|
||||
if (transferLines != null && !transferLines.isEmpty()) {
|
||||
for (Line transferLine : transferLines) {
|
||||
int origIndex = transferLine.stations.indexOf(origin);
|
||||
int destIndex = transferLine.stations.indexOf(origin
|
||||
.getOutboundTransferStation());
|
||||
public List<Route> getDirectRoutesForDestination(Station origin,
|
||||
Station dest, Station transferStation,
|
||||
Collection<Line> transferLines) {
|
||||
if (dest == null)
|
||||
return null;
|
||||
Boolean isNorth = null;
|
||||
List<Route> returnList = new ArrayList<Route>();
|
||||
final Collection<Line> applicableLines = Line.getLinesWithStations(
|
||||
this, dest);
|
||||
if (transferLines != null && !transferLines.isEmpty()) {
|
||||
for (Line transferLine : transferLines) {
|
||||
int origIndex = transferLine.stations.indexOf(origin);
|
||||
int destIndex = transferLine.stations.indexOf(origin
|
||||
.getOutboundTransferStation());
|
||||
|
||||
isNorth = (origIndex < destIndex);
|
||||
if (origin.invertDirection && transferLine.directionMayInvert) {
|
||||
isNorth = !isNorth;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Line line : applicableLines) {
|
||||
if (transferLines == null || transferLines.isEmpty()) {
|
||||
int origIndex = line.stations.indexOf(this);
|
||||
int destIndex = line.stations.indexOf(dest);
|
||||
isNorth = (origIndex < destIndex);
|
||||
if (origin.invertDirection && transferLine.directionMayInvert) {
|
||||
isNorth = !isNorth;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Line line : applicableLines) {
|
||||
if (transferLines == null || transferLines.isEmpty()) {
|
||||
int origIndex = line.stations.indexOf(this);
|
||||
int destIndex = line.stations.indexOf(dest);
|
||||
|
||||
isNorth = (origIndex < destIndex);
|
||||
if (line.directionMayInvert && this.invertDirection) {
|
||||
isNorth = !isNorth;
|
||||
}
|
||||
}
|
||||
Route route = new Route();
|
||||
route.setOrigin(origin);
|
||||
route.setDirectLine(line);
|
||||
if (this.equals(origin)) {
|
||||
route.setDestination(dest);
|
||||
} else {
|
||||
// This must be the outbound transfer station
|
||||
route.setDestination(origin.getOutboundTransferStation());
|
||||
route.setTransferLines(transferLines);
|
||||
}
|
||||
route.setDirection(isNorth ? "n" : "s");
|
||||
if (transferStation != null || line.requiresTransfer) {
|
||||
route.setTransfer(true);
|
||||
} else {
|
||||
route.setTransfer(false);
|
||||
}
|
||||
isNorth = (origIndex < destIndex);
|
||||
if (line.directionMayInvert && this.invertDirection) {
|
||||
isNorth = !isNorth;
|
||||
}
|
||||
}
|
||||
Route route = new Route();
|
||||
route.setOrigin(origin);
|
||||
route.setDirectLine(line);
|
||||
if (this.equals(origin)) {
|
||||
route.setDestination(dest);
|
||||
} else {
|
||||
// This must be the outbound transfer station
|
||||
route.setDestination(origin.getOutboundTransferStation());
|
||||
route.setTransferLines(transferLines);
|
||||
}
|
||||
route.setDirection(isNorth ? "n" : "s");
|
||||
if (transferStation != null || line.requiresTransfer) {
|
||||
route.setTransfer(true);
|
||||
} else {
|
||||
route.setTransfer(false);
|
||||
}
|
||||
|
||||
returnList.add(route);
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
returnList.add(route);
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
||||
public List<Route> getTransferRoutes(Station dest) {
|
||||
List<Route> returnList = new ArrayList<Route>();
|
||||
public List<Route> getTransferRoutes(Station dest) {
|
||||
List<Route> returnList = new ArrayList<Route>();
|
||||
|
||||
if (dest.getInboundTransferStation() != null) {
|
||||
// Try getting to the destination's inbound xfer station first
|
||||
returnList.addAll(getDirectRoutesForDestination(this,
|
||||
dest.getInboundTransferStation(),
|
||||
dest.getInboundTransferStation(), null));
|
||||
}
|
||||
if (dest.getInboundTransferStation() != null) {
|
||||
// Try getting to the destination's inbound xfer station first
|
||||
returnList.addAll(getDirectRoutesForDestination(this,
|
||||
dest.getInboundTransferStation(),
|
||||
dest.getInboundTransferStation(), null));
|
||||
}
|
||||
|
||||
if (returnList.isEmpty() && outboundTransferStation != null) {
|
||||
// Try getting from the outbound transfer station to the
|
||||
// destination next
|
||||
final Collection<Line> outboundTransferLines = Line
|
||||
.getLinesWithStations(this, getOutboundTransferStation());
|
||||
final List<Route> routesForDestination = getOutboundTransferStation()
|
||||
.getDirectRoutesForDestination(this, dest,
|
||||
getOutboundTransferStation(), outboundTransferLines);
|
||||
if (routesForDestination != null && !routesForDestination.isEmpty()) {
|
||||
returnList.addAll(routesForDestination);
|
||||
}
|
||||
}
|
||||
if (returnList.isEmpty() && outboundTransferStation != null) {
|
||||
// Try getting from the outbound transfer station to the
|
||||
// destination next
|
||||
final Collection<Line> outboundTransferLines = Line
|
||||
.getLinesWithStations(this, getOutboundTransferStation());
|
||||
final List<Route> routesForDestination = getOutboundTransferStation()
|
||||
.getDirectRoutesForDestination(this, dest,
|
||||
getOutboundTransferStation(), outboundTransferLines);
|
||||
if (routesForDestination != null && !routesForDestination.isEmpty()) {
|
||||
returnList.addAll(routesForDestination);
|
||||
}
|
||||
}
|
||||
|
||||
if (returnList.isEmpty()) {
|
||||
// Try getting from the outbound transfer station to the
|
||||
// destination's inbound xfer station
|
||||
final List<Route> routesForDestination = getDoubleTransferRoutes(dest);
|
||||
if (routesForDestination != null && !routesForDestination.isEmpty()) {
|
||||
returnList.addAll(routesForDestination);
|
||||
}
|
||||
}
|
||||
if (returnList.isEmpty()) {
|
||||
// Try getting from the outbound transfer station to the
|
||||
// destination's inbound xfer station
|
||||
final List<Route> routesForDestination = getDoubleTransferRoutes(dest);
|
||||
if (routesForDestination != null && !routesForDestination.isEmpty()) {
|
||||
returnList.addAll(routesForDestination);
|
||||
}
|
||||
}
|
||||
|
||||
return returnList;
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
||||
public List<Route> getDoubleTransferRoutes(Station dest) {
|
||||
if (getOutboundTransferStation() == null
|
||||
|| dest.getInboundTransferStation() == null)
|
||||
return new ArrayList<Route>();
|
||||
public List<Route> getDoubleTransferRoutes(Station dest) {
|
||||
if (getOutboundTransferStation() == null
|
||||
|| dest.getInboundTransferStation() == null)
|
||||
return new ArrayList<Route>();
|
||||
|
||||
// Get routes from the outbound transfer station to the
|
||||
// destination's inbound xfer station
|
||||
return getOutboundTransferStation().getDirectRoutesForDestination(this,
|
||||
dest.getInboundTransferStation(), getOutboundTransferStation(),
|
||||
Line.getLinesWithStations(this, getOutboundTransferStation()));
|
||||
}
|
||||
// Get routes from the outbound transfer station to the
|
||||
// destination's inbound xfer station
|
||||
return getOutboundTransferStation().getDirectRoutesForDestination(this,
|
||||
dest.getInboundTransferStation(), getOutboundTransferStation(),
|
||||
Line.getLinesWithStations(this, getOutboundTransferStation()));
|
||||
}
|
||||
|
||||
static public List<Station> getStationList() {
|
||||
List<Station> list = new ArrayList<Station>();
|
||||
for (Station station : values()) {
|
||||
if (!station.equals(Station.SPCL)) {
|
||||
list.add(station);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
static public List<Station> getStationList() {
|
||||
List<Station> list = new ArrayList<Station>();
|
||||
for (Station station : values()) {
|
||||
if (!station.equals(Station.SPCL)) {
|
||||
list.add(station);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isBetween(Station origin, Station destination, Line line) {
|
||||
int originIndex = line.stations.indexOf(origin);
|
||||
int destinationIndex = line.stations.indexOf(destination);
|
||||
int stationIndex = line.stations.indexOf(this);
|
||||
if (originIndex < 0 || destinationIndex < 0 || stationIndex < 0) {
|
||||
return false;
|
||||
}
|
||||
public boolean isBetween(Station origin, Station destination, Line line) {
|
||||
int originIndex = line.stations.indexOf(origin);
|
||||
int destinationIndex = line.stations.indexOf(destination);
|
||||
int stationIndex = line.stations.indexOf(this);
|
||||
if (originIndex < 0 || destinationIndex < 0 || stationIndex < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Math.abs(stationIndex - originIndex) < Math.abs(destinationIndex
|
||||
- originIndex);
|
||||
}
|
||||
return Math.abs(stationIndex - originIndex) < Math.abs(destinationIndex
|
||||
- originIndex);
|
||||
}
|
||||
}
|
||||
|
@ -12,149 +12,147 @@ import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class StationPair implements Parcelable {
|
||||
@JsonCreator
|
||||
public StationPair(@JsonProperty("origin") Station origin,
|
||||
@JsonProperty("destination") Station destination) {
|
||||
super();
|
||||
this.origin = origin;
|
||||
this.destination = destination;
|
||||
}
|
||||
@JsonCreator
|
||||
public StationPair(@JsonProperty("origin") Station origin,
|
||||
@JsonProperty("destination") Station destination) {
|
||||
super();
|
||||
this.origin = origin;
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
public StationPair(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
public StationPair(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public static StationPair createFromCursor(Cursor cursor) {
|
||||
StationPair pair = new StationPair(
|
||||
Station.getByAbbreviation(CursorUtils.getString(cursor,
|
||||
RoutesColumns.FROM_STATION)),
|
||||
Station.getByAbbreviation(CursorUtils.getString(cursor,
|
||||
RoutesColumns.TO_STATION)));
|
||||
pair.fare = CursorUtils.getString(cursor, RoutesColumns.FARE);
|
||||
pair.fareLastUpdated = CursorUtils.getLong(cursor,
|
||||
RoutesColumns.FARE_LAST_UPDATED);
|
||||
pair.averageTripLength = CursorUtils.getInteger(cursor,
|
||||
RoutesColumns.AVERAGE_TRIP_LENGTH);
|
||||
pair.averageTripSampleCount = CursorUtils.getInteger(cursor,
|
||||
RoutesColumns.AVERAGE_TRIP_SAMPLE_COUNT);
|
||||
return pair;
|
||||
}
|
||||
public static StationPair createFromCursor(Cursor cursor) {
|
||||
StationPair pair = new StationPair(
|
||||
Station.getByAbbreviation(CursorUtils.getString(cursor,
|
||||
RoutesColumns.FROM_STATION)),
|
||||
Station.getByAbbreviation(CursorUtils.getString(cursor,
|
||||
RoutesColumns.TO_STATION)));
|
||||
pair.fare = CursorUtils.getString(cursor, RoutesColumns.FARE);
|
||||
pair.fareLastUpdated = CursorUtils.getLong(cursor,
|
||||
RoutesColumns.FARE_LAST_UPDATED);
|
||||
pair.averageTripLength = CursorUtils.getInteger(cursor,
|
||||
RoutesColumns.AVERAGE_TRIP_LENGTH);
|
||||
pair.averageTripSampleCount = CursorUtils.getInteger(cursor,
|
||||
RoutesColumns.AVERAGE_TRIP_SAMPLE_COUNT);
|
||||
return pair;
|
||||
}
|
||||
|
||||
private Station origin;
|
||||
private Station destination;
|
||||
private String fare;
|
||||
private Station origin;
|
||||
private Station destination;
|
||||
private String fare;
|
||||
|
||||
private long fareLastUpdated;
|
||||
private int averageTripLength;
|
||||
private int averageTripSampleCount;
|
||||
private long fareLastUpdated;
|
||||
private int averageTripLength;
|
||||
private int averageTripSampleCount;
|
||||
|
||||
public Station getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
public Station getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
public Station getDestination() {
|
||||
return destination;
|
||||
}
|
||||
public Station getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
public String getFare() {
|
||||
return fare;
|
||||
}
|
||||
public String getFare() {
|
||||
return fare;
|
||||
}
|
||||
|
||||
public void setFare(String fare) {
|
||||
this.fare = fare;
|
||||
}
|
||||
public void setFare(String fare) {
|
||||
this.fare = fare;
|
||||
}
|
||||
|
||||
public long getFareLastUpdated() {
|
||||
return fareLastUpdated;
|
||||
}
|
||||
public long getFareLastUpdated() {
|
||||
return fareLastUpdated;
|
||||
}
|
||||
|
||||
public void setFareLastUpdated(long fareLastUpdated) {
|
||||
this.fareLastUpdated = fareLastUpdated;
|
||||
}
|
||||
public void setFareLastUpdated(long fareLastUpdated) {
|
||||
this.fareLastUpdated = fareLastUpdated;
|
||||
}
|
||||
|
||||
public int getAverageTripLength() {
|
||||
return averageTripLength;
|
||||
}
|
||||
public int getAverageTripLength() {
|
||||
return averageTripLength;
|
||||
}
|
||||
|
||||
public void setAverageTripLength(int averageTripLength) {
|
||||
this.averageTripLength = averageTripLength;
|
||||
}
|
||||
public void setAverageTripLength(int averageTripLength) {
|
||||
this.averageTripLength = averageTripLength;
|
||||
}
|
||||
|
||||
public int getAverageTripSampleCount() {
|
||||
return averageTripSampleCount;
|
||||
}
|
||||
public int getAverageTripSampleCount() {
|
||||
return averageTripSampleCount;
|
||||
}
|
||||
|
||||
public void setAverageTripSampleCount(int averageTripSampleCount) {
|
||||
this.averageTripSampleCount = averageTripSampleCount;
|
||||
}
|
||||
public void setAverageTripSampleCount(int averageTripSampleCount) {
|
||||
this.averageTripSampleCount = averageTripSampleCount;
|
||||
}
|
||||
|
||||
public boolean isBetweenStations(Station station1, Station station2) {
|
||||
return (origin.equals(station1) && destination.equals(station2))
|
||||
|| (origin.equals(station2) && destination.equals(station1));
|
||||
}
|
||||
public boolean isBetweenStations(Station station1, Station station2) {
|
||||
return (origin.equals(station1) && destination.equals(station2))
|
||||
|| (origin.equals(station2) && destination.equals(station1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result
|
||||
+ ((destination == null) ? 0 : destination.hashCode());
|
||||
result = prime * result + ((origin == null) ? 0 : origin.hashCode());
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result
|
||||
+ ((destination == null) ? 0 : destination.hashCode());
|
||||
result = prime * result + ((origin == null) ? 0 : origin.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean fareEquals(StationPair other) {
|
||||
if (other == null)
|
||||
return false;
|
||||
return ObjectUtils.equals(getFare(), other.getFare())
|
||||
&& ObjectUtils.equals(getFareLastUpdated(),
|
||||
other.getFareLastUpdated());
|
||||
}
|
||||
public boolean fareEquals(StationPair other) {
|
||||
if (other == null)
|
||||
return false;
|
||||
return ObjectUtils.equals(getFare(), other.getFare())
|
||||
&& ObjectUtils.equals(getFareLastUpdated(),
|
||||
other.getFareLastUpdated());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
StationPair other = (StationPair) obj;
|
||||
if (destination != other.destination)
|
||||
return false;
|
||||
if (origin != other.origin)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
StationPair other = (StationPair) obj;
|
||||
if (destination != other.destination)
|
||||
return false;
|
||||
return origin == other.origin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StationPair [origin=" + origin + ", destination=" + destination
|
||||
+ "]";
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StationPair [origin=" + origin + ", destination=" + destination
|
||||
+ "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(origin.abbreviation);
|
||||
dest.writeString(destination.abbreviation);
|
||||
}
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(origin.abbreviation);
|
||||
dest.writeString(destination.abbreviation);
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel in) {
|
||||
origin = Station.getByAbbreviation(in.readString());
|
||||
destination = Station.getByAbbreviation(in.readString());
|
||||
}
|
||||
private void readFromParcel(Parcel in) {
|
||||
origin = Station.getByAbbreviation(in.readString());
|
||||
destination = Station.getByAbbreviation(in.readString());
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<StationPair> CREATOR = new Parcelable.Creator<StationPair>() {
|
||||
public StationPair createFromParcel(Parcel in) {
|
||||
return new StationPair(in);
|
||||
}
|
||||
public static final Parcelable.Creator<StationPair> CREATOR = new Parcelable.Creator<StationPair>() {
|
||||
public StationPair createFromParcel(Parcel in) {
|
||||
return new StationPair(in);
|
||||
}
|
||||
|
||||
public StationPair[] newArray(int size) {
|
||||
return new StationPair[size];
|
||||
}
|
||||
};
|
||||
public StationPair[] newArray(int size) {
|
||||
return new StationPair[size];
|
||||
}
|
||||
};
|
||||
}
|
@ -3,6 +3,6 @@ package com.dougkeen.bart.model;
|
||||
|
||||
public interface TextProvider {
|
||||
|
||||
String getText(long tickNumber);
|
||||
String getText(long tickNumber);
|
||||
|
||||
}
|
||||
|
@ -23,118 +23,118 @@ import android.util.Xml;
|
||||
import com.dougkeen.bart.model.Alert;
|
||||
|
||||
public class AlertListConverter extends
|
||||
AbstractHttpMessageConverter<Alert.AlertList> {
|
||||
AbstractHttpMessageConverter<Alert.AlertList> {
|
||||
|
||||
@Override
|
||||
protected Alert.AlertList readInternal(
|
||||
Class<? extends Alert.AlertList> clazz,
|
||||
HttpInputMessage inputMessage) throws IOException,
|
||||
HttpMessageNotReadableException {
|
||||
StringWriter writer = new StringWriter();
|
||||
IOUtils.copy(inputMessage.getBody(), writer, "UTF-8");
|
||||
@Override
|
||||
protected Alert.AlertList readInternal(
|
||||
Class<? extends Alert.AlertList> clazz,
|
||||
HttpInputMessage inputMessage) throws IOException,
|
||||
HttpMessageNotReadableException {
|
||||
StringWriter writer = new StringWriter();
|
||||
IOUtils.copy(inputMessage.getBody(), writer, "UTF-8");
|
||||
|
||||
String xml = writer.toString();
|
||||
if (xml.length() == 0) {
|
||||
throw new IOException("Server returned blank xml document");
|
||||
}
|
||||
String xml = writer.toString();
|
||||
if (xml.length() == 0) {
|
||||
throw new IOException("Server returned blank xml document");
|
||||
}
|
||||
|
||||
AlertListHandler handler = new AlertListHandler();
|
||||
try {
|
||||
Xml.parse(xml, handler);
|
||||
} catch (SAXException e) {
|
||||
Log.e("AlertListConverter", "XML parsing error", e);
|
||||
return null;
|
||||
}
|
||||
AlertListHandler handler = new AlertListHandler();
|
||||
try {
|
||||
Xml.parse(xml, handler);
|
||||
} catch (SAXException e) {
|
||||
Log.e("AlertListConverter", "XML parsing error", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
return handler.getAlertList();
|
||||
}
|
||||
return handler.getAlertList();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supports(Class<?> clazz) {
|
||||
return Alert.AlertList.class.equals(clazz);
|
||||
}
|
||||
@Override
|
||||
protected boolean supports(Class<?> clazz) {
|
||||
return Alert.AlertList.class.equals(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MediaType> getSupportedMediaTypes() {
|
||||
final List<MediaType> supportedMediaTypes = new ArrayList<MediaType>();
|
||||
supportedMediaTypes.add(MediaType.TEXT_HTML);
|
||||
supportedMediaTypes.add(MediaType.TEXT_XML);
|
||||
supportedMediaTypes.addAll(super.getSupportedMediaTypes());
|
||||
return supportedMediaTypes;
|
||||
}
|
||||
@Override
|
||||
public List<MediaType> getSupportedMediaTypes() {
|
||||
final List<MediaType> supportedMediaTypes = new ArrayList<MediaType>();
|
||||
supportedMediaTypes.add(MediaType.TEXT_HTML);
|
||||
supportedMediaTypes.add(MediaType.TEXT_XML);
|
||||
supportedMediaTypes.addAll(super.getSupportedMediaTypes());
|
||||
return supportedMediaTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeInternal(Alert.AlertList arg0, HttpOutputMessage arg1)
|
||||
throws IOException, HttpMessageNotWritableException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
@Override
|
||||
protected void writeInternal(Alert.AlertList arg0, HttpOutputMessage arg1)
|
||||
throws IOException, HttpMessageNotWritableException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
private static class AlertListHandler extends DefaultHandler {
|
||||
private final static List<String> TAGS = Arrays.asList("bsa", "type",
|
||||
"description", "posted", "expires");
|
||||
private static class AlertListHandler extends DefaultHandler {
|
||||
private final static List<String> TAGS = Arrays.asList("bsa", "type",
|
||||
"description", "posted", "expires");
|
||||
|
||||
private String currentValue;
|
||||
private boolean isParsingTag;
|
||||
private Alert currentAlert;
|
||||
private Alert.AlertList returnList = new Alert.AlertList();
|
||||
private String currentValue;
|
||||
private boolean isParsingTag;
|
||||
private Alert currentAlert;
|
||||
private Alert.AlertList returnList = new Alert.AlertList();
|
||||
|
||||
public Alert.AlertList getAlertList() {
|
||||
return returnList;
|
||||
}
|
||||
public Alert.AlertList getAlertList() {
|
||||
return returnList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length)
|
||||
throws SAXException {
|
||||
if (isParsingTag) {
|
||||
currentValue = new String(ch, start, length);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length)
|
||||
throws SAXException {
|
||||
if (isParsingTag) {
|
||||
currentValue = new String(ch, start, length);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName,
|
||||
Attributes attributes) throws SAXException {
|
||||
if (TAGS.contains(localName)) {
|
||||
isParsingTag = true;
|
||||
}
|
||||
final int numberOfAttributes = attributes.getLength();
|
||||
if (localName.equals("bsa")) {
|
||||
for (int i = 0; i < numberOfAttributes; i++) {
|
||||
if (attributes.getLocalName(i).equalsIgnoreCase("id")) {
|
||||
currentAlert = new Alert(attributes.getValue(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName,
|
||||
Attributes attributes) throws SAXException {
|
||||
if (TAGS.contains(localName)) {
|
||||
isParsingTag = true;
|
||||
}
|
||||
final int numberOfAttributes = attributes.getLength();
|
||||
if (localName.equals("bsa")) {
|
||||
for (int i = 0; i < numberOfAttributes; i++) {
|
||||
if (attributes.getLocalName(i).equalsIgnoreCase("id")) {
|
||||
currentAlert = new Alert(attributes.getValue(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName)
|
||||
throws SAXException {
|
||||
if (currentAlert != null) {
|
||||
if (localName.equals("type")) {
|
||||
currentAlert.setType(currentValue);
|
||||
} else if (localName.equals("description")) {
|
||||
currentAlert.setDescription(currentValue);
|
||||
} else if (localName.equals("posted")) {
|
||||
currentAlert.setPostedTime(currentValue);
|
||||
} else if (localName.equals("expires")) {
|
||||
currentAlert.setExpiresTime(currentValue);
|
||||
} else if (localName.equals("bsa")) {
|
||||
returnList.addAlert(currentAlert);
|
||||
currentAlert = null;
|
||||
}
|
||||
}
|
||||
isParsingTag = false;
|
||||
currentValue = null;
|
||||
}
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName)
|
||||
throws SAXException {
|
||||
if (currentAlert != null) {
|
||||
if (localName.equals("type")) {
|
||||
currentAlert.setType(currentValue);
|
||||
} else if (localName.equals("description")) {
|
||||
currentAlert.setDescription(currentValue);
|
||||
} else if (localName.equals("posted")) {
|
||||
currentAlert.setPostedTime(currentValue);
|
||||
} else if (localName.equals("expires")) {
|
||||
currentAlert.setExpiresTime(currentValue);
|
||||
} else if (localName.equals("bsa")) {
|
||||
returnList.addAlert(currentAlert);
|
||||
currentAlert = null;
|
||||
}
|
||||
}
|
||||
isParsingTag = false;
|
||||
currentValue = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endDocument() throws SAXException {
|
||||
super.endDocument();
|
||||
if (!returnList.hasAlerts()) {
|
||||
returnList.setNoDelaysReported(true);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void endDocument() throws SAXException {
|
||||
super.endDocument();
|
||||
if (!returnList.hasAlerts()) {
|
||||
returnList.setNoDelaysReported(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -5,8 +5,8 @@ import com.dougkeen.bart.model.Constants;
|
||||
import com.googlecode.androidannotations.annotations.rest.Get;
|
||||
import com.googlecode.androidannotations.annotations.rest.Rest;
|
||||
|
||||
@Rest(rootUrl = "http://api.bart.gov", converters = { AlertListConverter.class })
|
||||
@Rest(rootUrl = "http://api.bart.gov", converters = {AlertListConverter.class})
|
||||
public interface AlertsClient {
|
||||
@Get("/api/bsa.aspx?cmd=bsa&key=" + Constants.API_KEY)
|
||||
Alert.AlertList getAlerts();
|
||||
@Get("/api/bsa.aspx?cmd=bsa&key=" + Constants.API_KEY)
|
||||
Alert.AlertList getAlerts();
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ import com.dougkeen.bart.model.Constants;
|
||||
import com.googlecode.androidannotations.annotations.rest.Get;
|
||||
import com.googlecode.androidannotations.annotations.rest.Rest;
|
||||
|
||||
@Rest(rootUrl = "http://api.bart.gov", converters = { ElevatorMessageConverter.class })
|
||||
@Rest(rootUrl = "http://api.bart.gov", converters = {ElevatorMessageConverter.class})
|
||||
public interface ElevatorClient {
|
||||
@Get("/api/bsa.aspx?cmd=elev&key=" + Constants.API_KEY)
|
||||
String getElevatorMessage();
|
||||
@Get("/api/bsa.aspx?cmd=elev&key=" + Constants.API_KEY)
|
||||
String getElevatorMessage();
|
||||
}
|
||||
|
@ -19,81 +19,81 @@ import android.util.Log;
|
||||
import android.util.Xml;
|
||||
|
||||
public class ElevatorMessageConverter extends
|
||||
AbstractHttpMessageConverter<String> {
|
||||
AbstractHttpMessageConverter<String> {
|
||||
|
||||
private static final String TAG = "ElevatorMessageConverter";
|
||||
private static final String TAG = "ElevatorMessageConverter";
|
||||
|
||||
@Override
|
||||
protected String readInternal(Class<? extends String> clazz,
|
||||
HttpInputMessage inputMessage) throws IOException,
|
||||
HttpMessageNotReadableException {
|
||||
@Override
|
||||
protected String readInternal(Class<? extends String> clazz,
|
||||
HttpInputMessage inputMessage) throws IOException,
|
||||
HttpMessageNotReadableException {
|
||||
|
||||
final ElevatorMessageHandler handler = new ElevatorMessageHandler();
|
||||
try {
|
||||
Xml.parse(new InputStreamReader(inputMessage.getBody()), handler);
|
||||
} catch (SAXException e) {
|
||||
Log.e(TAG, "Unable to parse elevator message", e);
|
||||
return null;
|
||||
}
|
||||
final ElevatorMessageHandler handler = new ElevatorMessageHandler();
|
||||
try {
|
||||
Xml.parse(new InputStreamReader(inputMessage.getBody()), handler);
|
||||
} catch (SAXException e) {
|
||||
Log.e(TAG, "Unable to parse elevator message", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
return handler.getMessage();
|
||||
}
|
||||
return handler.getMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supports(Class<?> arg0) {
|
||||
return String.class.equals(arg0);
|
||||
}
|
||||
@Override
|
||||
protected boolean supports(Class<?> arg0) {
|
||||
return String.class.equals(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MediaType> getSupportedMediaTypes() {
|
||||
final List<MediaType> supportedMediaTypes = new ArrayList<MediaType>();
|
||||
supportedMediaTypes.add(MediaType.TEXT_HTML);
|
||||
supportedMediaTypes.add(MediaType.TEXT_XML);
|
||||
supportedMediaTypes.addAll(super.getSupportedMediaTypes());
|
||||
return supportedMediaTypes;
|
||||
}
|
||||
@Override
|
||||
public List<MediaType> getSupportedMediaTypes() {
|
||||
final List<MediaType> supportedMediaTypes = new ArrayList<MediaType>();
|
||||
supportedMediaTypes.add(MediaType.TEXT_HTML);
|
||||
supportedMediaTypes.add(MediaType.TEXT_XML);
|
||||
supportedMediaTypes.addAll(super.getSupportedMediaTypes());
|
||||
return supportedMediaTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeInternal(String arg0, HttpOutputMessage arg1)
|
||||
throws IOException, HttpMessageNotWritableException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
@Override
|
||||
protected void writeInternal(String arg0, HttpOutputMessage arg1)
|
||||
throws IOException, HttpMessageNotWritableException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
private static class ElevatorMessageHandler extends DefaultHandler {
|
||||
private String currentValue;
|
||||
private boolean isParsingTag;
|
||||
private static class ElevatorMessageHandler extends DefaultHandler {
|
||||
private String currentValue;
|
||||
private boolean isParsingTag;
|
||||
|
||||
private String message;
|
||||
private String message;
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length)
|
||||
throws SAXException {
|
||||
if (isParsingTag) {
|
||||
currentValue = new String(ch, start, length);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length)
|
||||
throws SAXException {
|
||||
if (isParsingTag) {
|
||||
currentValue = new String(ch, start, length);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName,
|
||||
Attributes attributes) throws SAXException {
|
||||
if ("description".equals(localName)) {
|
||||
isParsingTag = true;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName,
|
||||
Attributes attributes) throws SAXException {
|
||||
if ("description".equals(localName)) {
|
||||
isParsingTag = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName)
|
||||
throws SAXException {
|
||||
if ("description".equals(localName)) {
|
||||
message = currentValue;
|
||||
}
|
||||
isParsingTag = false;
|
||||
currentValue = null;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName)
|
||||
throws SAXException {
|
||||
if ("description".equals(localName)) {
|
||||
message = currentValue;
|
||||
}
|
||||
isParsingTag = false;
|
||||
currentValue = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,104 +19,104 @@ import com.dougkeen.bart.model.Route;
|
||||
import com.dougkeen.bart.model.Station;
|
||||
|
||||
public class EtdContentHandler extends DefaultHandler {
|
||||
public EtdContentHandler(Station origin, Station destination,
|
||||
List<Route> routes) {
|
||||
super();
|
||||
realTimeDepartures = new RealTimeDepartures(origin, destination, routes);
|
||||
}
|
||||
public EtdContentHandler(Station origin, Station destination,
|
||||
List<Route> routes) {
|
||||
super();
|
||||
realTimeDepartures = new RealTimeDepartures(origin, destination, routes);
|
||||
}
|
||||
|
||||
private final static List<String> TAGS = Arrays.asList("date", "time",
|
||||
"abbreviation", "minutes", "platform", "direction", "length",
|
||||
"color", "hexcolor", "bikeflag");
|
||||
private final static List<String> TAGS = Arrays.asList("date", "time",
|
||||
"abbreviation", "minutes", "platform", "direction", "length",
|
||||
"color", "hexcolor", "bikeflag");
|
||||
|
||||
private RealTimeDepartures realTimeDepartures;
|
||||
private RealTimeDepartures realTimeDepartures;
|
||||
|
||||
public RealTimeDepartures getRealTimeDepartures() {
|
||||
return realTimeDepartures;
|
||||
}
|
||||
public RealTimeDepartures getRealTimeDepartures() {
|
||||
return realTimeDepartures;
|
||||
}
|
||||
|
||||
private String date;
|
||||
private String currentDestination;
|
||||
private String currentValue;
|
||||
private Departure currentDeparture;
|
||||
private boolean isParsingTag;
|
||||
private String date;
|
||||
private String currentDestination;
|
||||
private String currentValue;
|
||||
private Departure currentDeparture;
|
||||
private boolean isParsingTag;
|
||||
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length)
|
||||
throws SAXException {
|
||||
if (isParsingTag) {
|
||||
currentValue = new String(ch, start, length);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length)
|
||||
throws SAXException {
|
||||
if (isParsingTag) {
|
||||
currentValue = new String(ch, start, length);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName,
|
||||
Attributes attributes) throws SAXException {
|
||||
if (TAGS.contains(localName)) {
|
||||
isParsingTag = true;
|
||||
}
|
||||
if (localName.equals("estimate")) {
|
||||
currentDeparture = new Departure();
|
||||
currentDeparture.setTrainDestination(Station
|
||||
.getByAbbreviation(currentDestination));
|
||||
currentDeparture.setOrigin(realTimeDepartures.getOrigin());
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName,
|
||||
Attributes attributes) throws SAXException {
|
||||
if (TAGS.contains(localName)) {
|
||||
isParsingTag = true;
|
||||
}
|
||||
if (localName.equals("estimate")) {
|
||||
currentDeparture = new Departure();
|
||||
currentDeparture.setTrainDestination(Station
|
||||
.getByAbbreviation(currentDestination));
|
||||
currentDeparture.setOrigin(realTimeDepartures.getOrigin());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName)
|
||||
throws SAXException {
|
||||
if (localName.equals("date")) {
|
||||
date = currentValue;
|
||||
} else if (localName.equals("time")) {
|
||||
realTimeDepartures.setTime(Date.parse(date + " " + currentValue));
|
||||
} else if (localName.equals("abbreviation")) {
|
||||
currentDestination = currentValue;
|
||||
} else if (localName.equals("minutes")) {
|
||||
if (StringUtils.isNumeric(currentValue)) {
|
||||
currentDeparture.setMinutes(Integer.parseInt(currentValue));
|
||||
} else {
|
||||
currentDeparture.setMinutes(0);
|
||||
}
|
||||
} else if (localName.equals("platform")) {
|
||||
currentDeparture.setPlatform(currentValue);
|
||||
} else if (localName.equals("direction")) {
|
||||
currentDeparture.setDirection(currentValue);
|
||||
} else if (localName.equals("length")) {
|
||||
currentDeparture.setTrainLength(currentValue);
|
||||
} else if (localName.equals("color")) {
|
||||
try {
|
||||
if (currentValue.equalsIgnoreCase("WHITE")) {
|
||||
for (Line line : Line.values()) {
|
||||
if (line.stations.indexOf(currentDeparture
|
||||
.getTrainDestination()) >= 0
|
||||
&& line.stations.indexOf(realTimeDepartures
|
||||
.getDestination()) >= 0) {
|
||||
currentDeparture.setLine(line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
currentDeparture.setLine(Line.valueOf(currentValue));
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.w(Constants.TAG, "There is no line called '" + currentValue
|
||||
+ "'");
|
||||
}
|
||||
} else if (localName.equals("hexcolor")) {
|
||||
currentDeparture.setTrainDestinationColor("#ff"
|
||||
+ currentValue.substring(1));
|
||||
} else if (localName.equals("bikeflag")) {
|
||||
currentDeparture.setBikeAllowed(currentValue.equalsIgnoreCase("1"));
|
||||
} else if (localName.equals("estimate")) {
|
||||
realTimeDepartures.addDeparture(currentDeparture);
|
||||
currentDeparture = null;
|
||||
} else if (localName.equals("etd")) {
|
||||
currentDestination = null;
|
||||
} else if (localName.equals("station")) {
|
||||
realTimeDepartures.finalizeDeparturesList();
|
||||
}
|
||||
isParsingTag = false;
|
||||
currentValue = null;
|
||||
}
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName)
|
||||
throws SAXException {
|
||||
if (localName.equals("date")) {
|
||||
date = currentValue;
|
||||
} else if (localName.equals("time")) {
|
||||
realTimeDepartures.setTime(Date.parse(date + " " + currentValue));
|
||||
} else if (localName.equals("abbreviation")) {
|
||||
currentDestination = currentValue;
|
||||
} else if (localName.equals("minutes")) {
|
||||
if (StringUtils.isNumeric(currentValue)) {
|
||||
currentDeparture.setMinutes(Integer.parseInt(currentValue));
|
||||
} else {
|
||||
currentDeparture.setMinutes(0);
|
||||
}
|
||||
} else if (localName.equals("platform")) {
|
||||
currentDeparture.setPlatform(currentValue);
|
||||
} else if (localName.equals("direction")) {
|
||||
currentDeparture.setDirection(currentValue);
|
||||
} else if (localName.equals("length")) {
|
||||
currentDeparture.setTrainLength(currentValue);
|
||||
} else if (localName.equals("color")) {
|
||||
try {
|
||||
if (currentValue.equalsIgnoreCase("WHITE")) {
|
||||
for (Line line : Line.values()) {
|
||||
if (line.stations.indexOf(currentDeparture
|
||||
.getTrainDestination()) >= 0
|
||||
&& line.stations.indexOf(realTimeDepartures
|
||||
.getDestination()) >= 0) {
|
||||
currentDeparture.setLine(line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
currentDeparture.setLine(Line.valueOf(currentValue));
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.w(Constants.TAG, "There is no line called '" + currentValue
|
||||
+ "'");
|
||||
}
|
||||
} else if (localName.equals("hexcolor")) {
|
||||
currentDeparture.setTrainDestinationColor("#ff"
|
||||
+ currentValue.substring(1));
|
||||
} else if (localName.equals("bikeflag")) {
|
||||
currentDeparture.setBikeAllowed(currentValue.equalsIgnoreCase("1"));
|
||||
} else if (localName.equals("estimate")) {
|
||||
realTimeDepartures.addDeparture(currentDeparture);
|
||||
currentDeparture = null;
|
||||
} else if (localName.equals("etd")) {
|
||||
currentDestination = null;
|
||||
} else if (localName.equals("station")) {
|
||||
realTimeDepartures.finalizeDeparturesList();
|
||||
}
|
||||
isParsingTag = false;
|
||||
currentValue = null;
|
||||
}
|
||||
}
|
||||
|
@ -5,42 +5,42 @@ import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
public class FareContentHandler extends DefaultHandler {
|
||||
public FareContentHandler() {
|
||||
super();
|
||||
}
|
||||
public FareContentHandler() {
|
||||
super();
|
||||
}
|
||||
|
||||
private String currentValue;
|
||||
private boolean isParsingTag;
|
||||
private String fare;
|
||||
private String currentValue;
|
||||
private boolean isParsingTag;
|
||||
private String fare;
|
||||
|
||||
public String getFare() {
|
||||
return fare;
|
||||
}
|
||||
public String getFare() {
|
||||
return fare;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length)
|
||||
throws SAXException {
|
||||
if (isParsingTag) {
|
||||
currentValue = new String(ch, start, length);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length)
|
||||
throws SAXException {
|
||||
if (isParsingTag) {
|
||||
currentValue = new String(ch, start, length);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName,
|
||||
Attributes attributes) throws SAXException {
|
||||
if (localName.equals("fare")) {
|
||||
isParsingTag = true;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName,
|
||||
Attributes attributes) throws SAXException {
|
||||
if (localName.equals("fare")) {
|
||||
isParsingTag = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName)
|
||||
throws SAXException {
|
||||
if (localName.equals("fare")) {
|
||||
fare = "$" + currentValue;
|
||||
}
|
||||
isParsingTag = false;
|
||||
currentValue = null;
|
||||
}
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName)
|
||||
throws SAXException {
|
||||
if (localName.equals("fare")) {
|
||||
fare = "$" + currentValue;
|
||||
}
|
||||
isParsingTag = false;
|
||||
currentValue = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,132 +22,132 @@ import com.dougkeen.bart.model.Route;
|
||||
import com.dougkeen.bart.model.StationPair;
|
||||
|
||||
public abstract class GetRealTimeDeparturesTask extends
|
||||
AsyncTask<StationPair, Integer, RealTimeDepartures> {
|
||||
AsyncTask<StationPair, Integer, RealTimeDepartures> {
|
||||
|
||||
private final static String ETD_URL = "http://api.bart.gov/api/etd.aspx?cmd=etd&key="
|
||||
+ Constants.API_KEY + "&orig=%1$s&dir=%2$s";
|
||||
private final static String ETD_URL_NO_DIRECTION = "http://api.bart.gov/api/etd.aspx?cmd=etd&key="
|
||||
+ Constants.API_KEY + "&orig=%1$s";
|
||||
private final static int MAX_ATTEMPTS = 5;
|
||||
private final static String ETD_URL = "http://api.bart.gov/api/etd.aspx?cmd=etd&key="
|
||||
+ Constants.API_KEY + "&orig=%1$s&dir=%2$s";
|
||||
private final static String ETD_URL_NO_DIRECTION = "http://api.bart.gov/api/etd.aspx?cmd=etd&key="
|
||||
+ Constants.API_KEY + "&orig=%1$s";
|
||||
private final static int MAX_ATTEMPTS = 5;
|
||||
|
||||
private Exception mException;
|
||||
private Exception mException;
|
||||
|
||||
private List<Route> mRoutes;
|
||||
private List<Route> mRoutes;
|
||||
|
||||
private final boolean ignoreDirection;
|
||||
private final boolean ignoreDirection;
|
||||
|
||||
public GetRealTimeDeparturesTask(boolean ignoreDirection) {
|
||||
super();
|
||||
this.ignoreDirection = ignoreDirection;
|
||||
}
|
||||
public GetRealTimeDeparturesTask(boolean ignoreDirection) {
|
||||
super();
|
||||
this.ignoreDirection = ignoreDirection;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RealTimeDepartures doInBackground(StationPair... paramsArray) {
|
||||
// Always expect one param
|
||||
StationPair params = paramsArray[0];
|
||||
@Override
|
||||
protected RealTimeDepartures doInBackground(StationPair... paramsArray) {
|
||||
// Always expect one param
|
||||
StationPair params = paramsArray[0];
|
||||
|
||||
mRoutes = params.getOrigin().getDirectRoutesForDestination(
|
||||
params.getDestination());
|
||||
mRoutes = params.getOrigin().getDirectRoutesForDestination(
|
||||
params.getDestination());
|
||||
|
||||
boolean hasDirectLine = false;
|
||||
for (Route route : mRoutes) {
|
||||
if (!route.hasTransfer()) {
|
||||
hasDirectLine = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
boolean hasDirectLine = false;
|
||||
for (Route route : mRoutes) {
|
||||
if (!route.hasTransfer()) {
|
||||
hasDirectLine = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mRoutes.isEmpty()
|
||||
|| (params.getOrigin().transferFriendly && !hasDirectLine)) {
|
||||
mRoutes.addAll(params.getOrigin().getTransferRoutes(
|
||||
params.getDestination()));
|
||||
}
|
||||
if (mRoutes.isEmpty()
|
||||
|| (params.getOrigin().transferFriendly && !hasDirectLine)) {
|
||||
mRoutes.addAll(params.getOrigin().getTransferRoutes(
|
||||
params.getDestination()));
|
||||
}
|
||||
|
||||
if (!isCancelled()) {
|
||||
return getDeparturesFromNetwork(params, 0);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (!isCancelled()) {
|
||||
return getDeparturesFromNetwork(params, 0);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private RealTimeDepartures getDeparturesFromNetwork(StationPair params,
|
||||
int attemptNumber) {
|
||||
String xml = null;
|
||||
try {
|
||||
String url;
|
||||
if (ignoreDirection || params.getOrigin().endOfLine) {
|
||||
url = String.format(ETD_URL_NO_DIRECTION,
|
||||
params.getOrigin().abbreviation);
|
||||
} else {
|
||||
url = String.format(ETD_URL, params.getOrigin().abbreviation,
|
||||
mRoutes.get(0).getDirection());
|
||||
}
|
||||
private RealTimeDepartures getDeparturesFromNetwork(StationPair params,
|
||||
int attemptNumber) {
|
||||
String xml = null;
|
||||
try {
|
||||
String url;
|
||||
if (ignoreDirection || params.getOrigin().endOfLine) {
|
||||
url = String.format(ETD_URL_NO_DIRECTION,
|
||||
params.getOrigin().abbreviation);
|
||||
} else {
|
||||
url = String.format(ETD_URL, params.getOrigin().abbreviation,
|
||||
mRoutes.get(0).getDirection());
|
||||
}
|
||||
|
||||
HttpUriRequest request = new HttpGet(url);
|
||||
HttpUriRequest request = new HttpGet(url);
|
||||
|
||||
EtdContentHandler handler = new EtdContentHandler(
|
||||
params.getOrigin(), params.getDestination(), mRoutes);
|
||||
if (isCancelled()) {
|
||||
return null;
|
||||
}
|
||||
EtdContentHandler handler = new EtdContentHandler(
|
||||
params.getOrigin(), params.getDestination(), mRoutes);
|
||||
if (isCancelled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
HttpResponse response = NetworkUtils.executeWithRecovery(request);
|
||||
HttpResponse response = NetworkUtils.executeWithRecovery(request);
|
||||
|
||||
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
|
||||
throw new IOException("Server returned "
|
||||
+ response.getStatusLine().toString());
|
||||
}
|
||||
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
|
||||
throw new IOException("Server returned "
|
||||
+ response.getStatusLine().toString());
|
||||
}
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
IOUtils.copy(response.getEntity().getContent(), writer, "UTF-8");
|
||||
StringWriter writer = new StringWriter();
|
||||
IOUtils.copy(response.getEntity().getContent(), writer, "UTF-8");
|
||||
|
||||
xml = writer.toString();
|
||||
if (xml.length() == 0) {
|
||||
throw new IOException("Server returned blank xml document");
|
||||
}
|
||||
xml = writer.toString();
|
||||
if (xml.length() == 0) {
|
||||
throw new IOException("Server returned blank xml document");
|
||||
}
|
||||
|
||||
try {
|
||||
Xml.parse(xml, handler);
|
||||
} catch (Exception e) {
|
||||
mException = new IOException("Server returned malformed xml: "
|
||||
+ xml);
|
||||
return null;
|
||||
}
|
||||
final RealTimeDepartures realTimeDepartures = handler
|
||||
.getRealTimeDepartures();
|
||||
return realTimeDepartures;
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
if (attemptNumber < MAX_ATTEMPTS - 1) {
|
||||
try {
|
||||
Log.w(Constants.TAG,
|
||||
"Attempt to contact server failed... retrying in 3s",
|
||||
e);
|
||||
Thread.sleep(3000);
|
||||
} catch (InterruptedException interrupt) {
|
||||
// Ignore... just go on to next attempt
|
||||
}
|
||||
return getDeparturesFromNetwork(params, attemptNumber + 1);
|
||||
} else {
|
||||
mException = new Exception("Could not contact BART system", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
Xml.parse(xml, handler);
|
||||
} catch (Exception e) {
|
||||
mException = new IOException("Server returned malformed xml: "
|
||||
+ xml);
|
||||
return null;
|
||||
}
|
||||
final RealTimeDepartures realTimeDepartures = handler
|
||||
.getRealTimeDepartures();
|
||||
return realTimeDepartures;
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
if (attemptNumber < MAX_ATTEMPTS - 1) {
|
||||
try {
|
||||
Log.w(Constants.TAG,
|
||||
"Attempt to contact server failed... retrying in 3s",
|
||||
e);
|
||||
Thread.sleep(3000);
|
||||
} catch (InterruptedException interrupt) {
|
||||
// Ignore... just go on to next attempt
|
||||
}
|
||||
return getDeparturesFromNetwork(params, attemptNumber + 1);
|
||||
} else {
|
||||
mException = new Exception("Could not contact BART system", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(RealTimeDepartures result) {
|
||||
if (result != null) {
|
||||
onResult(result);
|
||||
} else {
|
||||
onError(mException);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void onPostExecute(RealTimeDepartures result) {
|
||||
if (result != null) {
|
||||
onResult(result);
|
||||
} else {
|
||||
onError(mException);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void onResult(RealTimeDepartures result);
|
||||
public abstract void onResult(RealTimeDepartures result);
|
||||
|
||||
public abstract void onError(Exception exception);
|
||||
public abstract void onError(Exception exception);
|
||||
}
|
||||
|
@ -20,106 +20,106 @@ import com.dougkeen.bart.model.Constants;
|
||||
import com.dougkeen.bart.model.Station;
|
||||
|
||||
public abstract class GetRouteFareTask extends
|
||||
AsyncTask<GetRouteFareTask.Params, Integer, String> {
|
||||
AsyncTask<GetRouteFareTask.Params, Integer, String> {
|
||||
|
||||
private final static int MAX_ATTEMPTS = 5;
|
||||
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 int MAX_ATTEMPTS = 5;
|
||||
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 Exception mException;
|
||||
private Exception mException;
|
||||
|
||||
private String fare;
|
||||
private String fare;
|
||||
|
||||
@Override
|
||||
protected String doInBackground(Params... paramsArray) {
|
||||
Params params = paramsArray[0];
|
||||
@Override
|
||||
protected String doInBackground(Params... paramsArray) {
|
||||
Params params = paramsArray[0];
|
||||
|
||||
if (!isCancelled()) {
|
||||
return getFareFromNetwork(params, 0);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (!isCancelled()) {
|
||||
return getFareFromNetwork(params, 0);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String getFareFromNetwork(Params params, int attemptNumber) {
|
||||
String xml = null;
|
||||
private String getFareFromNetwork(Params params, int attemptNumber) {
|
||||
String xml = null;
|
||||
|
||||
try {
|
||||
HttpUriRequest request = new HttpGet(
|
||||
String.format(FARE_URL, params.origin.abbreviation,
|
||||
params.destination.abbreviation));
|
||||
try {
|
||||
HttpUriRequest request = new HttpGet(
|
||||
String.format(FARE_URL, params.origin.abbreviation,
|
||||
params.destination.abbreviation));
|
||||
|
||||
FareContentHandler handler = new FareContentHandler();
|
||||
if (isCancelled()) {
|
||||
return null;
|
||||
}
|
||||
FareContentHandler handler = new FareContentHandler();
|
||||
if (isCancelled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
HttpResponse response = NetworkUtils.executeWithRecovery(request);
|
||||
HttpResponse response = NetworkUtils.executeWithRecovery(request);
|
||||
|
||||
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
|
||||
throw new IOException("Server returned "
|
||||
+ response.getStatusLine().toString());
|
||||
}
|
||||
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
|
||||
throw new IOException("Server returned "
|
||||
+ response.getStatusLine().toString());
|
||||
}
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
IOUtils.copy(response.getEntity().getContent(), writer, "UTF-8");
|
||||
StringWriter writer = new StringWriter();
|
||||
IOUtils.copy(response.getEntity().getContent(), writer, "UTF-8");
|
||||
|
||||
xml = writer.toString();
|
||||
if (xml.length() == 0) {
|
||||
throw new IOException("Server returned blank xml document");
|
||||
}
|
||||
xml = writer.toString();
|
||||
if (xml.length() == 0) {
|
||||
throw new IOException("Server returned blank xml document");
|
||||
}
|
||||
|
||||
Xml.parse(xml, handler);
|
||||
fare = handler.getFare();
|
||||
return fare;
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
if (attemptNumber < MAX_ATTEMPTS - 1) {
|
||||
try {
|
||||
Log.w(Constants.TAG,
|
||||
"Attempt to contact server failed... retrying in 3s",
|
||||
e);
|
||||
Thread.sleep(3000);
|
||||
} catch (InterruptedException interrupt) {
|
||||
// Ignore... just go on to next attempt
|
||||
}
|
||||
return getFareFromNetwork(params, attemptNumber + 1);
|
||||
} else {
|
||||
mException = new Exception("Could not contact BART system", e);
|
||||
return null;
|
||||
}
|
||||
} catch (SAXException e) {
|
||||
mException = new Exception(
|
||||
"Could not understand response from BART system: " + xml, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Xml.parse(xml, handler);
|
||||
fare = handler.getFare();
|
||||
return fare;
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
if (attemptNumber < MAX_ATTEMPTS - 1) {
|
||||
try {
|
||||
Log.w(Constants.TAG,
|
||||
"Attempt to contact server failed... retrying in 3s",
|
||||
e);
|
||||
Thread.sleep(3000);
|
||||
} catch (InterruptedException interrupt) {
|
||||
// Ignore... just go on to next attempt
|
||||
}
|
||||
return getFareFromNetwork(params, attemptNumber + 1);
|
||||
} else {
|
||||
mException = new Exception("Could not contact BART system", e);
|
||||
return null;
|
||||
}
|
||||
} catch (SAXException e) {
|
||||
mException = new Exception(
|
||||
"Could not understand response from BART system: " + xml, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Params {
|
||||
public Params(Station origin, Station destination) {
|
||||
super();
|
||||
this.origin = origin;
|
||||
this.destination = destination;
|
||||
}
|
||||
public static class Params {
|
||||
public Params(Station origin, Station destination) {
|
||||
super();
|
||||
this.origin = origin;
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
public final Station origin;
|
||||
public final Station destination;
|
||||
}
|
||||
public final Station origin;
|
||||
public final Station destination;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String result) {
|
||||
if (result != null) {
|
||||
onResult(fare);
|
||||
} else {
|
||||
onError(mException);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void onPostExecute(String result) {
|
||||
if (result != null) {
|
||||
onResult(fare);
|
||||
} else {
|
||||
onError(mException);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void onResult(String fare);
|
||||
public abstract void onResult(String fare);
|
||||
|
||||
public abstract void onError(Exception exception);
|
||||
public abstract void onError(Exception exception);
|
||||
|
||||
}
|
@ -21,98 +21,98 @@ import com.dougkeen.bart.model.ScheduleInformation;
|
||||
import com.dougkeen.bart.model.StationPair;
|
||||
|
||||
public abstract class GetScheduleInformationTask extends
|
||||
AsyncTask<StationPair, Integer, ScheduleInformation> {
|
||||
AsyncTask<StationPair, Integer, ScheduleInformation> {
|
||||
|
||||
private final static String SCHED_URL = "http://api.bart.gov/api/sched.aspx?cmd=depart&key="
|
||||
+ Constants.API_KEY + "&orig=%1$s&dest=%2$s&b=1&a=4";
|
||||
private final static String SCHED_URL = "http://api.bart.gov/api/sched.aspx?cmd=depart&key="
|
||||
+ Constants.API_KEY + "&orig=%1$s&dest=%2$s&b=1&a=4";
|
||||
|
||||
private final static int MAX_ATTEMPTS = 5;
|
||||
private final static int MAX_ATTEMPTS = 5;
|
||||
|
||||
private Exception mException;
|
||||
private Exception mException;
|
||||
|
||||
@Override
|
||||
protected ScheduleInformation doInBackground(StationPair... paramsArray) {
|
||||
// Always expect one param
|
||||
StationPair params = paramsArray[0];
|
||||
@Override
|
||||
protected ScheduleInformation doInBackground(StationPair... paramsArray) {
|
||||
// Always expect one param
|
||||
StationPair params = paramsArray[0];
|
||||
|
||||
if (!isCancelled()) {
|
||||
return getScheduleFromNetwork(params, 0);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (!isCancelled()) {
|
||||
return getScheduleFromNetwork(params, 0);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private ScheduleInformation getScheduleFromNetwork(StationPair params,
|
||||
int attemptNumber) {
|
||||
String xml = null;
|
||||
try {
|
||||
String url = String.format(SCHED_URL,
|
||||
params.getOrigin().abbreviation,
|
||||
params.getDestination().abbreviation);
|
||||
private ScheduleInformation getScheduleFromNetwork(StationPair params,
|
||||
int attemptNumber) {
|
||||
String xml = null;
|
||||
try {
|
||||
String url = String.format(SCHED_URL,
|
||||
params.getOrigin().abbreviation,
|
||||
params.getDestination().abbreviation);
|
||||
|
||||
HttpUriRequest request = new HttpGet(url);
|
||||
HttpUriRequest request = new HttpGet(url);
|
||||
|
||||
if (isCancelled()) {
|
||||
return null;
|
||||
}
|
||||
if (isCancelled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ScheduleContentHandler handler = new ScheduleContentHandler(
|
||||
params.getOrigin(), params.getDestination());
|
||||
ScheduleContentHandler handler = new ScheduleContentHandler(
|
||||
params.getOrigin(), params.getDestination());
|
||||
|
||||
HttpResponse response = NetworkUtils.executeWithRecovery(request);
|
||||
HttpResponse response = NetworkUtils.executeWithRecovery(request);
|
||||
|
||||
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
|
||||
throw new IOException("Server returned "
|
||||
+ response.getStatusLine().toString());
|
||||
}
|
||||
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
|
||||
throw new IOException("Server returned "
|
||||
+ response.getStatusLine().toString());
|
||||
}
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
IOUtils.copy(response.getEntity().getContent(), writer, "UTF-8");
|
||||
StringWriter writer = new StringWriter();
|
||||
IOUtils.copy(response.getEntity().getContent(), writer, "UTF-8");
|
||||
|
||||
xml = writer.toString();
|
||||
if (xml.length() == 0) {
|
||||
throw new IOException("Server returned blank xml document");
|
||||
}
|
||||
xml = writer.toString();
|
||||
if (xml.length() == 0) {
|
||||
throw new IOException("Server returned blank xml document");
|
||||
}
|
||||
|
||||
Xml.parse(xml, handler);
|
||||
final ScheduleInformation schedule = handler.getSchedule();
|
||||
return schedule;
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
if (attemptNumber < MAX_ATTEMPTS - 1) {
|
||||
try {
|
||||
Log.w(Constants.TAG,
|
||||
"Attempt to contact server failed... retrying in 3s",
|
||||
e);
|
||||
Thread.sleep(3000);
|
||||
} catch (InterruptedException interrupt) {
|
||||
// Ignore... just go on to next attempt
|
||||
}
|
||||
return getScheduleFromNetwork(params, attemptNumber + 1);
|
||||
} else {
|
||||
mException = new Exception("Could not contact BART system", e);
|
||||
return null;
|
||||
}
|
||||
} catch (SAXException e) {
|
||||
mException = new Exception(
|
||||
"Could not understand response from BART system: " + xml, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Xml.parse(xml, handler);
|
||||
final ScheduleInformation schedule = handler.getSchedule();
|
||||
return schedule;
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
if (attemptNumber < MAX_ATTEMPTS - 1) {
|
||||
try {
|
||||
Log.w(Constants.TAG,
|
||||
"Attempt to contact server failed... retrying in 3s",
|
||||
e);
|
||||
Thread.sleep(3000);
|
||||
} catch (InterruptedException interrupt) {
|
||||
// Ignore... just go on to next attempt
|
||||
}
|
||||
return getScheduleFromNetwork(params, attemptNumber + 1);
|
||||
} else {
|
||||
mException = new Exception("Could not contact BART system", e);
|
||||
return null;
|
||||
}
|
||||
} catch (SAXException e) {
|
||||
mException = new Exception(
|
||||
"Could not understand response from BART system: " + xml, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(ScheduleInformation result) {
|
||||
if (result != null) {
|
||||
onResult(result);
|
||||
} else {
|
||||
onError(mException);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void onPostExecute(ScheduleInformation result) {
|
||||
if (result != null) {
|
||||
onResult(result);
|
||||
} else {
|
||||
onError(mException);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void onResult(ScheduleInformation result);
|
||||
public abstract void onResult(ScheduleInformation result);
|
||||
|
||||
public abstract void onError(Exception exception);
|
||||
public abstract void onError(Exception exception);
|
||||
}
|
||||
|
@ -13,28 +13,28 @@ import org.apache.http.params.HttpParams;
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
public static HttpResponse executeWithRecovery(final HttpUriRequest request)
|
||||
throws IOException, ClientProtocolException {
|
||||
try {
|
||||
return getHttpClient().execute(request);
|
||||
} catch (IllegalStateException e) {
|
||||
// try again... this is a rare error
|
||||
return getHttpClient().execute(request);
|
||||
}
|
||||
}
|
||||
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;
|
||||
static final int CONNECTION_TIMEOUT_MILLIS = 10000;
|
||||
|
||||
}
|
||||
|
@ -19,149 +19,149 @@ import com.dougkeen.bart.model.ScheduleItem;
|
||||
import com.dougkeen.bart.model.Station;
|
||||
|
||||
public class ScheduleContentHandler extends DefaultHandler {
|
||||
public ScheduleContentHandler(Station origin, Station destination) {
|
||||
super();
|
||||
schedule = new ScheduleInformation(origin, destination);
|
||||
}
|
||||
public ScheduleContentHandler(Station origin, Station destination) {
|
||||
super();
|
||||
schedule = new ScheduleInformation(origin, destination);
|
||||
}
|
||||
|
||||
private final static List<String> TAGS = Arrays.asList("date", "time",
|
||||
"trip", "leg");
|
||||
private final static List<String> TAGS = Arrays.asList("date", "time",
|
||||
"trip", "leg");
|
||||
|
||||
private final static DateFormat TRIP_DATE_FORMAT;
|
||||
private final static DateFormat REQUEST_DATE_FORMAT;
|
||||
private final static DateFormat TRIP_DATE_FORMAT;
|
||||
private final static DateFormat REQUEST_DATE_FORMAT;
|
||||
|
||||
private final static TimeZone PACIFIC_TIME = TimeZone
|
||||
.getTimeZone("America/Los_Angeles");
|
||||
private final static TimeZone PACIFIC_TIME = TimeZone
|
||||
.getTimeZone("America/Los_Angeles");
|
||||
|
||||
static {
|
||||
TRIP_DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy h:mm a");
|
||||
REQUEST_DATE_FORMAT = new SimpleDateFormat("MMM d, yyyy h:mm a");
|
||||
static {
|
||||
TRIP_DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy h:mm a");
|
||||
REQUEST_DATE_FORMAT = new SimpleDateFormat("MMM d, yyyy h:mm a");
|
||||
|
||||
TRIP_DATE_FORMAT.setTimeZone(PACIFIC_TIME);
|
||||
REQUEST_DATE_FORMAT.setTimeZone(PACIFIC_TIME);
|
||||
}
|
||||
TRIP_DATE_FORMAT.setTimeZone(PACIFIC_TIME);
|
||||
REQUEST_DATE_FORMAT.setTimeZone(PACIFIC_TIME);
|
||||
}
|
||||
|
||||
private ScheduleInformation schedule;
|
||||
private ScheduleInformation schedule;
|
||||
|
||||
public ScheduleInformation getSchedule() {
|
||||
return schedule;
|
||||
}
|
||||
public ScheduleInformation getSchedule() {
|
||||
return schedule;
|
||||
}
|
||||
|
||||
private String currentValue;
|
||||
private boolean isParsingTag;
|
||||
private String currentValue;
|
||||
private boolean isParsingTag;
|
||||
|
||||
private String requestDate;
|
||||
private String requestTime;
|
||||
private String requestDate;
|
||||
private String requestTime;
|
||||
|
||||
private ScheduleItem currentTrip;
|
||||
private ScheduleItem currentTrip;
|
||||
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length)
|
||||
throws SAXException {
|
||||
if (isParsingTag) {
|
||||
currentValue = new String(ch, start, length);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length)
|
||||
throws SAXException {
|
||||
if (isParsingTag) {
|
||||
currentValue = new String(ch, start, length);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName,
|
||||
Attributes attributes) throws SAXException {
|
||||
if (TAGS.contains(localName)) {
|
||||
isParsingTag = true;
|
||||
}
|
||||
final int numberOfAttributes = attributes.getLength();
|
||||
if (localName.equals("trip")) {
|
||||
currentTrip = new ScheduleItem();
|
||||
String originDate = null;
|
||||
String originTime = null;
|
||||
String destinationDate = null;
|
||||
String destinationTime = null;
|
||||
for (int i = 0; i < numberOfAttributes; i++) {
|
||||
if (attributes.getLocalName(i).equalsIgnoreCase("origin")) {
|
||||
currentTrip.setOrigin(Station.getByAbbreviation(attributes
|
||||
.getValue(i)));
|
||||
} else if (attributes.getLocalName(i).equalsIgnoreCase(
|
||||
"destination")) {
|
||||
currentTrip.setDestination(Station
|
||||
.getByAbbreviation(attributes.getValue(i)));
|
||||
} else if (attributes.getLocalName(i).equalsIgnoreCase("fare")) {
|
||||
currentTrip.setFare(attributes.getValue(i));
|
||||
} else if (attributes.getLocalName(i).equalsIgnoreCase(
|
||||
"origTimeMin")) {
|
||||
originTime = attributes.getValue(i);
|
||||
} else if (attributes.getLocalName(i).equalsIgnoreCase(
|
||||
"origTimeDate")) {
|
||||
originDate = attributes.getValue(i);
|
||||
} else if (attributes.getLocalName(i).equalsIgnoreCase(
|
||||
"destTimeMin")) {
|
||||
destinationTime = attributes.getValue(i);
|
||||
} else if (attributes.getLocalName(i).equalsIgnoreCase(
|
||||
"destTimeDate")) {
|
||||
destinationDate = attributes.getValue(i);
|
||||
} else if (attributes.getLocalName(i).equalsIgnoreCase(
|
||||
"bikeFlag")) {
|
||||
currentTrip.setBikesAllowed(attributes.getValue(i).equals(
|
||||
"1"));
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName,
|
||||
Attributes attributes) throws SAXException {
|
||||
if (TAGS.contains(localName)) {
|
||||
isParsingTag = true;
|
||||
}
|
||||
final int numberOfAttributes = attributes.getLength();
|
||||
if (localName.equals("trip")) {
|
||||
currentTrip = new ScheduleItem();
|
||||
String originDate = null;
|
||||
String originTime = null;
|
||||
String destinationDate = null;
|
||||
String destinationTime = null;
|
||||
for (int i = 0; i < numberOfAttributes; i++) {
|
||||
if (attributes.getLocalName(i).equalsIgnoreCase("origin")) {
|
||||
currentTrip.setOrigin(Station.getByAbbreviation(attributes
|
||||
.getValue(i)));
|
||||
} else if (attributes.getLocalName(i).equalsIgnoreCase(
|
||||
"destination")) {
|
||||
currentTrip.setDestination(Station
|
||||
.getByAbbreviation(attributes.getValue(i)));
|
||||
} else if (attributes.getLocalName(i).equalsIgnoreCase("fare")) {
|
||||
currentTrip.setFare(attributes.getValue(i));
|
||||
} else if (attributes.getLocalName(i).equalsIgnoreCase(
|
||||
"origTimeMin")) {
|
||||
originTime = attributes.getValue(i);
|
||||
} else if (attributes.getLocalName(i).equalsIgnoreCase(
|
||||
"origTimeDate")) {
|
||||
originDate = attributes.getValue(i);
|
||||
} else if (attributes.getLocalName(i).equalsIgnoreCase(
|
||||
"destTimeMin")) {
|
||||
destinationTime = attributes.getValue(i);
|
||||
} else if (attributes.getLocalName(i).equalsIgnoreCase(
|
||||
"destTimeDate")) {
|
||||
destinationDate = attributes.getValue(i);
|
||||
} else if (attributes.getLocalName(i).equalsIgnoreCase(
|
||||
"bikeFlag")) {
|
||||
currentTrip.setBikesAllowed(attributes.getValue(i).equals(
|
||||
"1"));
|
||||
}
|
||||
}
|
||||
|
||||
long departTime = parseDate(TRIP_DATE_FORMAT, originDate,
|
||||
originTime);
|
||||
if (departTime > 0)
|
||||
currentTrip.setDepartureTime(departTime);
|
||||
long departTime = parseDate(TRIP_DATE_FORMAT, originDate,
|
||||
originTime);
|
||||
if (departTime > 0)
|
||||
currentTrip.setDepartureTime(departTime);
|
||||
|
||||
long arriveTime = parseDate(TRIP_DATE_FORMAT, destinationDate,
|
||||
destinationTime);
|
||||
if (arriveTime > 0)
|
||||
currentTrip.setArrivalTime(arriveTime);
|
||||
long arriveTime = parseDate(TRIP_DATE_FORMAT, destinationDate,
|
||||
destinationTime);
|
||||
if (arriveTime > 0)
|
||||
currentTrip.setArrivalTime(arriveTime);
|
||||
|
||||
schedule.addTrip(currentTrip);
|
||||
}
|
||||
if (localName.equals("leg")) {
|
||||
String legNumber = null;
|
||||
for (int i = 0; i < numberOfAttributes; i++) {
|
||||
if (attributes.getLocalName(i).equals("order")) {
|
||||
legNumber = attributes.getValue(i);
|
||||
} else if (attributes.getLocalName(i)
|
||||
.equals("trainHeadStation") && "1".equals(legNumber)) {
|
||||
currentTrip.setTrainHeadStation(attributes.getValue(i)
|
||||
.toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
schedule.addTrip(currentTrip);
|
||||
}
|
||||
if (localName.equals("leg")) {
|
||||
String legNumber = null;
|
||||
for (int i = 0; i < numberOfAttributes; i++) {
|
||||
if (attributes.getLocalName(i).equals("order")) {
|
||||
legNumber = attributes.getValue(i);
|
||||
} else if (attributes.getLocalName(i)
|
||||
.equals("trainHeadStation") && "1".equals(legNumber)) {
|
||||
currentTrip.setTrainHeadStation(attributes.getValue(i)
|
||||
.toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long parseDate(DateFormat format, String dateString,
|
||||
String timeString) {
|
||||
if (dateString == null || timeString == null) {
|
||||
return -1;
|
||||
}
|
||||
try {
|
||||
return format.parse(dateString + " " + timeString).getTime();
|
||||
} catch (ParseException e) {
|
||||
Log.e(Constants.TAG, "Unable to parse datetime '" + dateString
|
||||
+ " " + timeString + "'", e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
private long parseDate(DateFormat format, String dateString,
|
||||
String timeString) {
|
||||
if (dateString == null || timeString == null) {
|
||||
return -1;
|
||||
}
|
||||
try {
|
||||
return format.parse(dateString + " " + timeString).getTime();
|
||||
} catch (ParseException e) {
|
||||
Log.e(Constants.TAG, "Unable to parse datetime '" + dateString
|
||||
+ " " + timeString + "'", e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName)
|
||||
throws SAXException {
|
||||
if (localName.equals("date")) {
|
||||
requestDate = currentValue;
|
||||
} else if (localName.equals("time")) {
|
||||
requestTime = currentValue;
|
||||
}
|
||||
isParsingTag = false;
|
||||
currentValue = null;
|
||||
}
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName)
|
||||
throws SAXException {
|
||||
if (localName.equals("date")) {
|
||||
requestDate = currentValue;
|
||||
} else if (localName.equals("time")) {
|
||||
requestTime = currentValue;
|
||||
}
|
||||
isParsingTag = false;
|
||||
currentValue = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endDocument() {
|
||||
long date = parseDate(REQUEST_DATE_FORMAT, requestDate, requestTime);
|
||||
if (date > 0) {
|
||||
schedule.setDate(date);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void endDocument() {
|
||||
long date = parseDate(REQUEST_DATE_FORMAT, requestDate, requestTime);
|
||||
if (date > 0) {
|
||||
schedule.setDate(date);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,28 +12,28 @@ import com.dougkeen.util.WakeLocker;
|
||||
|
||||
public class AlarmBroadcastReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
BartRunnerApplication application = (BartRunnerApplication) context
|
||||
.getApplicationContext();
|
||||
final Departure boardedDeparture = application.getBoardedDeparture(true);
|
||||
if (boardedDeparture == null) {
|
||||
// Nothing to notify about
|
||||
return;
|
||||
}
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
BartRunnerApplication application = (BartRunnerApplication) context
|
||||
.getApplicationContext();
|
||||
final Departure boardedDeparture = application.getBoardedDeparture(true);
|
||||
if (boardedDeparture == null) {
|
||||
// Nothing to notify about
|
||||
return;
|
||||
}
|
||||
|
||||
WakeLocker.acquire(context);
|
||||
WakeLocker.acquire(context);
|
||||
|
||||
application.setPlayAlarmRingtone(true);
|
||||
application.setPlayAlarmRingtone(true);
|
||||
|
||||
Intent targetIntent = new Intent(context, ViewDeparturesActivity.class);
|
||||
targetIntent.putExtra(Constants.STATION_PAIR_EXTRA,
|
||||
boardedDeparture.getStationPair());
|
||||
targetIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
Intent targetIntent = new Intent(context, ViewDeparturesActivity.class);
|
||||
targetIntent.putExtra(Constants.STATION_PAIR_EXTRA,
|
||||
boardedDeparture.getStationPair());
|
||||
targetIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
context.startActivity(targetIntent);
|
||||
context.startActivity(targetIntent);
|
||||
|
||||
boardedDeparture.notifyAlarmHasBeenHandled();
|
||||
}
|
||||
boardedDeparture.notifyAlarmHasBeenHandled();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,229 +24,229 @@ import com.dougkeen.bart.services.EtdService.EtdServiceListener;
|
||||
import com.dougkeen.util.Observer;
|
||||
|
||||
public class BoardedDepartureService extends Service implements
|
||||
EtdServiceListener {
|
||||
EtdServiceListener {
|
||||
|
||||
private static final int DEPARTURE_NOTIFICATION_ID = 123;
|
||||
private static final int DEPARTURE_NOTIFICATION_ID = 123;
|
||||
|
||||
private volatile Looper mServiceLooper;
|
||||
private volatile ServiceHandler mServiceHandler;
|
||||
private volatile Looper mServiceLooper;
|
||||
private volatile ServiceHandler mServiceHandler;
|
||||
|
||||
private boolean mBound = false;
|
||||
private EtdService mEtdService;
|
||||
private StationPair mStationPair;
|
||||
private NotificationManager mNotificationManager;
|
||||
private AlarmManager mAlarmManager;
|
||||
private Handler mHandler;
|
||||
private boolean mHasShutDown = false;
|
||||
private boolean mBound = false;
|
||||
private EtdService mEtdService;
|
||||
private StationPair mStationPair;
|
||||
private NotificationManager mNotificationManager;
|
||||
private AlarmManager mAlarmManager;
|
||||
private Handler mHandler;
|
||||
private boolean mHasShutDown = false;
|
||||
|
||||
public BoardedDepartureService() {
|
||||
super();
|
||||
}
|
||||
public BoardedDepartureService() {
|
||||
super();
|
||||
}
|
||||
|
||||
private static final class ServiceHandler extends Handler {
|
||||
private final WeakReference<BoardedDepartureService> mServiceRef;
|
||||
private static final class ServiceHandler extends Handler {
|
||||
private final WeakReference<BoardedDepartureService> mServiceRef;
|
||||
|
||||
public ServiceHandler(Looper looper,
|
||||
BoardedDepartureService boardedDepartureService) {
|
||||
super(looper);
|
||||
mServiceRef = new WeakReference<BoardedDepartureService>(
|
||||
boardedDepartureService);
|
||||
}
|
||||
public ServiceHandler(Looper looper,
|
||||
BoardedDepartureService boardedDepartureService) {
|
||||
super(looper);
|
||||
mServiceRef = new WeakReference<BoardedDepartureService>(
|
||||
boardedDepartureService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
BoardedDepartureService service = mServiceRef.get();
|
||||
if (service != null) {
|
||||
service.onHandleIntent((Intent) msg.obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
BoardedDepartureService service = mServiceRef.get();
|
||||
if (service != null) {
|
||||
service.onHandleIntent((Intent) msg.obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
mEtdService = null;
|
||||
mBound = false;
|
||||
}
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
mEtdService = null;
|
||||
mBound = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
mEtdService = ((EtdServiceBinder) service).getService();
|
||||
if (getStationPair() != null) {
|
||||
mEtdService.registerListener(BoardedDepartureService.this,
|
||||
false);
|
||||
}
|
||||
mBound = true;
|
||||
}
|
||||
};
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
mEtdService = ((EtdServiceBinder) service).getService();
|
||||
if (getStationPair() != null) {
|
||||
mEtdService.registerListener(BoardedDepartureService.this,
|
||||
false);
|
||||
}
|
||||
mBound = true;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
HandlerThread thread = new HandlerThread(
|
||||
"BartRunnerNotificationService");
|
||||
thread.start();
|
||||
@Override
|
||||
public void onCreate() {
|
||||
HandlerThread thread = new HandlerThread(
|
||||
"BartRunnerNotificationService");
|
||||
thread.start();
|
||||
|
||||
mServiceLooper = thread.getLooper();
|
||||
mServiceHandler = new ServiceHandler(mServiceLooper, this);
|
||||
mServiceLooper = thread.getLooper();
|
||||
mServiceHandler = new ServiceHandler(mServiceLooper, this);
|
||||
|
||||
bindService(EtdService_.intent(this).get(), mConnection,
|
||||
Context.BIND_AUTO_CREATE);
|
||||
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
|
||||
mHandler = new Handler();
|
||||
super.onCreate();
|
||||
}
|
||||
bindService(EtdService_.intent(this).get(), mConnection,
|
||||
Context.BIND_AUTO_CREATE);
|
||||
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
|
||||
mHandler = new Handler();
|
||||
super.onCreate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(Intent intent, int startId) {
|
||||
Message msg = mServiceHandler.obtainMessage();
|
||||
msg.arg1 = startId;
|
||||
msg.obj = intent;
|
||||
mServiceHandler.sendMessage(msg);
|
||||
}
|
||||
@Override
|
||||
public void onStart(Intent intent, int startId) {
|
||||
Message msg = mServiceHandler.obtainMessage();
|
||||
msg.arg1 = startId;
|
||||
msg.obj = intent;
|
||||
mServiceHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
mHasShutDown = false;
|
||||
onStart(intent, startId);
|
||||
return START_REDELIVER_INTENT;
|
||||
}
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
mHasShutDown = false;
|
||||
onStart(intent, startId);
|
||||
return START_REDELIVER_INTENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
shutDown(true);
|
||||
if (mBound)
|
||||
unbindService(mConnection);
|
||||
mServiceLooper.quit();
|
||||
super.onDestroy();
|
||||
}
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
shutDown(true);
|
||||
if (mBound)
|
||||
unbindService(mConnection);
|
||||
mServiceLooper.quit();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
protected void onHandleIntent(Intent intent) {
|
||||
if (intent == null)
|
||||
return;
|
||||
protected void onHandleIntent(Intent intent) {
|
||||
if (intent == null)
|
||||
return;
|
||||
|
||||
final BartRunnerApplication application = (BartRunnerApplication) getApplication();
|
||||
final Departure boardedDeparture;
|
||||
if (intent.hasExtra("departure")) {
|
||||
boardedDeparture = intent.getExtras().getParcelable("departure");
|
||||
} else {
|
||||
boardedDeparture = application.getBoardedDeparture();
|
||||
}
|
||||
if (boardedDeparture == null) {
|
||||
// Nothing to notify about
|
||||
if (mNotificationManager != null) {
|
||||
mNotificationManager.cancel(DEPARTURE_NOTIFICATION_ID);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (intent.getBooleanExtra("cancelNotifications", false)
|
||||
|| intent.getBooleanExtra("clearBoardedDeparture", false)) {
|
||||
// We want to cancel the alarm
|
||||
boardedDeparture
|
||||
.cancelAlarm(getApplicationContext(), mAlarmManager);
|
||||
if (intent.getBooleanExtra("clearBoardedDeparture", false)) {
|
||||
application.setBoardedDeparture(null);
|
||||
shutDown(false);
|
||||
} else {
|
||||
updateNotification();
|
||||
}
|
||||
return;
|
||||
}
|
||||
final BartRunnerApplication application = (BartRunnerApplication) getApplication();
|
||||
final Departure boardedDeparture;
|
||||
if (intent.hasExtra("departure")) {
|
||||
boardedDeparture = intent.getExtras().getParcelable("departure");
|
||||
} else {
|
||||
boardedDeparture = application.getBoardedDeparture();
|
||||
}
|
||||
if (boardedDeparture == null) {
|
||||
// Nothing to notify about
|
||||
if (mNotificationManager != null) {
|
||||
mNotificationManager.cancel(DEPARTURE_NOTIFICATION_ID);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (intent.getBooleanExtra("cancelNotifications", false)
|
||||
|| intent.getBooleanExtra("clearBoardedDeparture", false)) {
|
||||
// We want to cancel the alarm
|
||||
boardedDeparture
|
||||
.cancelAlarm(getApplicationContext(), mAlarmManager);
|
||||
if (intent.getBooleanExtra("clearBoardedDeparture", false)) {
|
||||
application.setBoardedDeparture(null);
|
||||
shutDown(false);
|
||||
} else {
|
||||
updateNotification();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
StationPair oldStationPair = mStationPair;
|
||||
mStationPair = boardedDeparture.getStationPair();
|
||||
StationPair oldStationPair = mStationPair;
|
||||
mStationPair = boardedDeparture.getStationPair();
|
||||
|
||||
if (mEtdService != null && mStationPair != null
|
||||
&& !mStationPair.equals(oldStationPair)) {
|
||||
mEtdService.unregisterListener(this);
|
||||
}
|
||||
if (mEtdService != null && mStationPair != null
|
||||
&& !mStationPair.equals(oldStationPair)) {
|
||||
mEtdService.unregisterListener(this);
|
||||
}
|
||||
|
||||
if (getStationPair() != null && mEtdService != null) {
|
||||
mEtdService.registerListener(this, false);
|
||||
}
|
||||
if (getStationPair() != null && mEtdService != null) {
|
||||
mEtdService.registerListener(this, false);
|
||||
}
|
||||
|
||||
boardedDeparture.getAlarmLeadTimeMinutesObservable().registerObserver(
|
||||
new Observer<Integer>() {
|
||||
@Override
|
||||
public void onUpdate(Integer newValue) {
|
||||
updateNotification();
|
||||
}
|
||||
});
|
||||
boardedDeparture.getAlarmPendingObservable().registerObserver(
|
||||
new Observer<Boolean>() {
|
||||
@Override
|
||||
public void onUpdate(Boolean newValue) {
|
||||
updateNotification();
|
||||
}
|
||||
});
|
||||
boardedDeparture.getAlarmLeadTimeMinutesObservable().registerObserver(
|
||||
new Observer<Integer>() {
|
||||
@Override
|
||||
public void onUpdate(Integer newValue) {
|
||||
updateNotification();
|
||||
}
|
||||
});
|
||||
boardedDeparture.getAlarmPendingObservable().registerObserver(
|
||||
new Observer<Boolean>() {
|
||||
@Override
|
||||
public void onUpdate(Boolean newValue) {
|
||||
updateNotification();
|
||||
}
|
||||
});
|
||||
|
||||
updateNotification();
|
||||
updateNotification();
|
||||
|
||||
pollDepartureStatus();
|
||||
}
|
||||
pollDepartureStatus();
|
||||
}
|
||||
|
||||
private void updateAlarm() {
|
||||
Departure boardedDeparture = ((BartRunnerApplication) getApplication())
|
||||
.getBoardedDeparture();
|
||||
if (boardedDeparture != null) {
|
||||
boardedDeparture
|
||||
.updateAlarm(getApplicationContext(), mAlarmManager);
|
||||
}
|
||||
}
|
||||
private void updateAlarm() {
|
||||
Departure boardedDeparture = ((BartRunnerApplication) getApplication())
|
||||
.getBoardedDeparture();
|
||||
if (boardedDeparture != null) {
|
||||
boardedDeparture
|
||||
.updateAlarm(getApplicationContext(), mAlarmManager);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onETDChanged(List<Departure> departures) {
|
||||
final Departure boardedDeparture = ((BartRunnerApplication) getApplication())
|
||||
.getBoardedDeparture();
|
||||
for (Departure departure : departures) {
|
||||
if (departure.equals(boardedDeparture)
|
||||
&& (boardedDeparture.getMeanSecondsLeft() != departure
|
||||
.getMeanSecondsLeft() || boardedDeparture
|
||||
.getUncertaintySeconds() != departure
|
||||
.getUncertaintySeconds())) {
|
||||
boardedDeparture.mergeEstimate(departure);
|
||||
// Also merge back, in case boardedDeparture estimate is better
|
||||
departure.mergeEstimate(boardedDeparture);
|
||||
@Override
|
||||
public void onETDChanged(List<Departure> departures) {
|
||||
final Departure boardedDeparture = ((BartRunnerApplication) getApplication())
|
||||
.getBoardedDeparture();
|
||||
for (Departure departure : departures) {
|
||||
if (departure.equals(boardedDeparture)
|
||||
&& (boardedDeparture.getMeanSecondsLeft() != departure
|
||||
.getMeanSecondsLeft() || boardedDeparture
|
||||
.getUncertaintySeconds() != departure
|
||||
.getUncertaintySeconds())) {
|
||||
boardedDeparture.mergeEstimate(departure);
|
||||
// Also merge back, in case boardedDeparture estimate is better
|
||||
departure.mergeEstimate(boardedDeparture);
|
||||
|
||||
updateAlarm();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
updateAlarm();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String errorMessage) {
|
||||
// Do nothing
|
||||
}
|
||||
@Override
|
||||
public void onError(String errorMessage) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestStarted() {
|
||||
// Do nothing
|
||||
}
|
||||
@Override
|
||||
public void onRequestStarted() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestEnded() {
|
||||
// Do nothing
|
||||
}
|
||||
@Override
|
||||
public void onRequestEnded() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public StationPair getStationPair() {
|
||||
return mStationPair;
|
||||
}
|
||||
@Override
|
||||
public StationPair getStationPair() {
|
||||
return mStationPair;
|
||||
}
|
||||
|
||||
private long mNextScheduledCheckClockTime = 0;
|
||||
private long mNextScheduledCheckClockTime = 0;
|
||||
|
||||
private void pollDepartureStatus() {
|
||||
final Departure boardedDeparture = ((BartRunnerApplication) getApplication())
|
||||
.getBoardedDeparture();
|
||||
private void pollDepartureStatus() {
|
||||
final Departure boardedDeparture = ((BartRunnerApplication) getApplication())
|
||||
.getBoardedDeparture();
|
||||
|
||||
if (boardedDeparture == null || boardedDeparture.hasDeparted()) {
|
||||
shutDown(false);
|
||||
return;
|
||||
}
|
||||
if (boardedDeparture == null || boardedDeparture.hasDeparted()) {
|
||||
shutDown(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mEtdService != null) {
|
||||
/*
|
||||
if (mEtdService != null) {
|
||||
/*
|
||||
* Make sure we're still listening for ETD changes (in case weak ref
|
||||
* was garbage collected). Not a huge fan of this approach, but I
|
||||
* think I'd rather keep the weak references to avoid memory leaks
|
||||
@ -255,73 +255,73 @@ public class BoardedDepartureService extends Service implements
|
||||
* few constant-time map operations, so there shouldn't be a big
|
||||
* performance hit.
|
||||
*/
|
||||
mEtdService.registerListener(this, false);
|
||||
}
|
||||
mEtdService.registerListener(this, false);
|
||||
}
|
||||
|
||||
boardedDeparture.updateAlarm(getApplicationContext(), mAlarmManager);
|
||||
boardedDeparture.updateAlarm(getApplicationContext(), mAlarmManager);
|
||||
|
||||
updateNotification();
|
||||
updateNotification();
|
||||
|
||||
final int pollIntervalMillis = getPollIntervalMillis();
|
||||
final long scheduledCheckClockTime = System.currentTimeMillis()
|
||||
+ pollIntervalMillis;
|
||||
if (mNextScheduledCheckClockTime < scheduledCheckClockTime) {
|
||||
mHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
pollDepartureStatus();
|
||||
}
|
||||
}, pollIntervalMillis);
|
||||
mNextScheduledCheckClockTime = scheduledCheckClockTime;
|
||||
}
|
||||
}
|
||||
final int pollIntervalMillis = getPollIntervalMillis();
|
||||
final long scheduledCheckClockTime = System.currentTimeMillis()
|
||||
+ pollIntervalMillis;
|
||||
if (mNextScheduledCheckClockTime < scheduledCheckClockTime) {
|
||||
mHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
pollDepartureStatus();
|
||||
}
|
||||
}, pollIntervalMillis);
|
||||
mNextScheduledCheckClockTime = scheduledCheckClockTime;
|
||||
}
|
||||
}
|
||||
|
||||
private void shutDown(boolean isBeingDestroyed) {
|
||||
if (!mHasShutDown) {
|
||||
mHasShutDown = true;
|
||||
if (mEtdService != null) {
|
||||
mEtdService.unregisterListener(this);
|
||||
}
|
||||
if (mNotificationManager != null) {
|
||||
mNotificationManager.cancel(DEPARTURE_NOTIFICATION_ID);
|
||||
}
|
||||
if (!isBeingDestroyed)
|
||||
stopSelf();
|
||||
}
|
||||
}
|
||||
private void shutDown(boolean isBeingDestroyed) {
|
||||
if (!mHasShutDown) {
|
||||
mHasShutDown = true;
|
||||
if (mEtdService != null) {
|
||||
mEtdService.unregisterListener(this);
|
||||
}
|
||||
if (mNotificationManager != null) {
|
||||
mNotificationManager.cancel(DEPARTURE_NOTIFICATION_ID);
|
||||
}
|
||||
if (!isBeingDestroyed)
|
||||
stopSelf();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNotification() {
|
||||
if (mHasShutDown) {
|
||||
if (mEtdService != null) {
|
||||
mEtdService.unregisterListener(this);
|
||||
}
|
||||
return;
|
||||
}
|
||||
private void updateNotification() {
|
||||
if (mHasShutDown) {
|
||||
if (mEtdService != null) {
|
||||
mEtdService.unregisterListener(this);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final Departure boardedDeparture = ((BartRunnerApplication) getApplication())
|
||||
.getBoardedDeparture();
|
||||
if (boardedDeparture != null) {
|
||||
mNotificationManager.notify(DEPARTURE_NOTIFICATION_ID,
|
||||
boardedDeparture
|
||||
.createNotification(getApplicationContext()));
|
||||
}
|
||||
}
|
||||
final Departure boardedDeparture = ((BartRunnerApplication) getApplication())
|
||||
.getBoardedDeparture();
|
||||
if (boardedDeparture != null) {
|
||||
mNotificationManager.notify(DEPARTURE_NOTIFICATION_ID,
|
||||
boardedDeparture
|
||||
.createNotification(getApplicationContext()));
|
||||
}
|
||||
}
|
||||
|
||||
private int getPollIntervalMillis() {
|
||||
final Departure boardedDeparture = ((BartRunnerApplication) getApplication())
|
||||
.getBoardedDeparture();
|
||||
private int getPollIntervalMillis() {
|
||||
final Departure boardedDeparture = ((BartRunnerApplication) getApplication())
|
||||
.getBoardedDeparture();
|
||||
|
||||
if (boardedDeparture.getSecondsUntilAlarm() > 3 * 60) {
|
||||
return 15 * 1000;
|
||||
} else {
|
||||
return 6 * 1000;
|
||||
}
|
||||
}
|
||||
if (boardedDeparture.getSecondsUntilAlarm() > 3 * 60) {
|
||||
return 15 * 1000;
|
||||
} else {
|
||||
return 6 * 1000;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
// Doesn't support binding
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
// Doesn't support binding
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -5,46 +5,46 @@ import java.util.WeakHashMap;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
public class Observable<T> {
|
||||
private T value;
|
||||
private WeakHashMap<Observer<T>, Boolean> listeners = new WeakHashMap<Observer<T>, Boolean>();
|
||||
private T value;
|
||||
private WeakHashMap<Observer<T>, Boolean> listeners = new WeakHashMap<Observer<T>, Boolean>();
|
||||
|
||||
public Observable() {
|
||||
super();
|
||||
}
|
||||
public Observable() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Observable(T value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
public Observable(T value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(T value) {
|
||||
if (!ObjectUtils.equals(this.value, value)) {
|
||||
this.value = value;
|
||||
notifyOfChange(value);
|
||||
}
|
||||
}
|
||||
public void setValue(T value) {
|
||||
if (!ObjectUtils.equals(this.value, value)) {
|
||||
this.value = value;
|
||||
notifyOfChange(value);
|
||||
}
|
||||
}
|
||||
|
||||
public void registerObserver(Observer<T> observer) {
|
||||
listeners.put(observer, true);
|
||||
}
|
||||
public void registerObserver(Observer<T> observer) {
|
||||
listeners.put(observer, true);
|
||||
}
|
||||
|
||||
public void unregisterObserver(Observer<T> observer) {
|
||||
listeners.remove(observer);
|
||||
}
|
||||
public void unregisterObserver(Observer<T> observer) {
|
||||
listeners.remove(observer);
|
||||
}
|
||||
|
||||
public void unregisterAllObservers() {
|
||||
listeners.clear();
|
||||
}
|
||||
public void unregisterAllObservers() {
|
||||
listeners.clear();
|
||||
}
|
||||
|
||||
protected void notifyOfChange(T value) {
|
||||
for (Observer<T> listener : listeners.keySet()) {
|
||||
if (listener != null) {
|
||||
listener.onUpdate(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
protected void notifyOfChange(T value) {
|
||||
for (Observer<T> listener : listeners.keySet()) {
|
||||
if (listener != null) {
|
||||
listener.onUpdate(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,5 +2,5 @@ package com.dougkeen.util;
|
||||
|
||||
|
||||
public interface Observer<T> {
|
||||
void onUpdate(final T newValue);
|
||||
void onUpdate(final T newValue);
|
||||
}
|
||||
|
@ -6,23 +6,23 @@ import android.os.PowerManager;
|
||||
import com.dougkeen.bart.model.Constants;
|
||||
|
||||
public abstract class WakeLocker {
|
||||
private static PowerManager.WakeLock wakeLock;
|
||||
private static PowerManager.WakeLock wakeLock;
|
||||
|
||||
public static void acquire(Context ctx) {
|
||||
if (wakeLock != null)
|
||||
wakeLock.release();
|
||||
public static void acquire(Context ctx) {
|
||||
if (wakeLock != null)
|
||||
wakeLock.release();
|
||||
|
||||
PowerManager pm = (PowerManager) ctx
|
||||
.getSystemService(Context.POWER_SERVICE);
|
||||
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK
|
||||
| PowerManager.ACQUIRE_CAUSES_WAKEUP
|
||||
| PowerManager.ON_AFTER_RELEASE, Constants.TAG);
|
||||
wakeLock.acquire();
|
||||
}
|
||||
PowerManager pm = (PowerManager) ctx
|
||||
.getSystemService(Context.POWER_SERVICE);
|
||||
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK
|
||||
| PowerManager.ACQUIRE_CAUSES_WAKEUP
|
||||
| PowerManager.ON_AFTER_RELEASE, Constants.TAG);
|
||||
wakeLock.acquire();
|
||||
}
|
||||
|
||||
public static void release() {
|
||||
if (wakeLock != null)
|
||||
wakeLock.release();
|
||||
wakeLock = null;
|
||||
}
|
||||
public static void release() {
|
||||
if (wakeLock != null)
|
||||
wakeLock.release();
|
||||
wakeLock = null;
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle" >
|
||||
android:shape="rectangle">
|
||||
|
||||
<size android:width="15dp" />
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:bart="http://schemas.android.com/apk/res/com.dougkeen.bart"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent" >
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/destinationColorBar"
|
||||
@ -17,7 +17,7 @@
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_toRightOf="@id/destinationColorBar" >
|
||||
android:layout_toRightOf="@id/destinationColorBar">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/destinationText"
|
||||
|
@ -2,7 +2,7 @@
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:bart="http://schemas.android.com/apk/res/com.dougkeen.bart"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent" >
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/destinationColorBar"
|
||||
@ -17,7 +17,7 @@
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_toRightOf="@id/destinationColorBar" >
|
||||
android:layout_toRightOf="@id/destinationColorBar">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/destinationText"
|
||||
|
@ -3,7 +3,7 @@
|
||||
xmlns:bart="http://schemas.android.com/apk/res/com.dougkeen.bart"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical" >
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/listTitle"
|
||||
@ -20,8 +20,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:padding="10dp"
|
||||
android:visibility="gone" >
|
||||
</com.dougkeen.bart.controls.YourTrainLayout>
|
||||
android:visibility="gone"></com.dougkeen.bart.controls.YourTrainLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/empty"
|
||||
|
@ -4,7 +4,7 @@
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingRight="5dp" >
|
||||
android:paddingRight="5dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/dragHandle"
|
||||
|
@ -4,7 +4,7 @@
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical" >
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.mobeta.android.dslv.DragSortListView
|
||||
android:id="@android:id/list"
|
||||
@ -43,7 +43,7 @@
|
||||
style="ButtonBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom" >
|
||||
android:layout_gravity="bottom">
|
||||
|
||||
<Button
|
||||
android:id="@+id/quickLookupButton"
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="45dp" >
|
||||
android:layout_height="45dp">
|
||||
|
||||
<ProgressBar
|
||||
style="?android:attr/progressBarStyleSmallInverse"
|
||||
|
@ -3,7 +3,7 @@
|
||||
xmlns:holo="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical" >
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<View
|
||||
android:id="@+id/titleDivider"
|
||||
@ -36,8 +36,7 @@
|
||||
android:paddingRight="5dp"
|
||||
android:paddingTop="15dip"
|
||||
android:text="@string/origin"
|
||||
android:textSize="15sp" >
|
||||
</TextView>
|
||||
android:textSize="15sp"></TextView>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/destination_spinner"
|
||||
@ -63,8 +62,7 @@
|
||||
android:paddingRight="5dp"
|
||||
android:paddingTop="15dip"
|
||||
android:text="@string/destination"
|
||||
android:textSize="15sp" >
|
||||
</TextView>
|
||||
android:textSize="15sp"></TextView>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/return_checkbox"
|
||||
|
@ -3,14 +3,13 @@
|
||||
xmlns:holo="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal" >
|
||||
android:orientation="horizontal">
|
||||
|
||||
<NumberPicker
|
||||
android:id="@+id/numberPicker"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" >
|
||||
</NumberPicker>
|
||||
android:layout_weight="1"></NumberPicker>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView1"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:bart="http://schemas.android.com/apk/res/com.dougkeen.bart" >
|
||||
xmlns:bart="http://schemas.android.com/apk/res/com.dougkeen.bart">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/alarmText"
|
||||
@ -11,8 +11,7 @@
|
||||
android:drawableLeft="@drawable/ic_action_alarm"
|
||||
android:gravity="center_vertical"
|
||||
android:textSize="16dp"
|
||||
android:visibility="gone" >
|
||||
</TextView>
|
||||
android:visibility="gone"></TextView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/yourTrainHeader"
|
||||
|
@ -1,9 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/boardTrain"
|
||||
android:icon="@drawable/ic_action_boarding"
|
||||
android:showAsAction="ifRoom|withText"
|
||||
android:title="@string/getting_on_this_train">
|
||||
</item>
|
||||
android:title="@string/getting_on_this_train"></item>
|
||||
</menu>
|
@ -1,17 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/view"
|
||||
android:icon="@drawable/ic_action_departure"
|
||||
android:showAsAction="ifRoom|withText"
|
||||
android:title="@string/view_departures">
|
||||
</item>
|
||||
android:title="@string/view_departures"></item>
|
||||
<item
|
||||
android:id="@+id/delete"
|
||||
android:icon="@drawable/ic_action_delete"
|
||||
android:showAsAction="ifRoom|withText"
|
||||
android:title="@string/delete">
|
||||
</item>
|
||||
android:title="@string/delete"></item>
|
||||
|
||||
</menu>
|
@ -1,17 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/view_on_bart_site_button"
|
||||
android:icon="@drawable/ic_action_web"
|
||||
android:showAsAction="never"
|
||||
android:title="@string/view_on_bart_site">
|
||||
</item>
|
||||
android:title="@string/view_on_bart_site"></item>
|
||||
<item
|
||||
android:id="@+id/view_system_map_button"
|
||||
android:icon="@drawable/ic_action_map"
|
||||
android:showAsAction="ifRoom|withText"
|
||||
android:title="@string/view_system_map">
|
||||
</item>
|
||||
android:title="@string/view_system_map"></item>
|
||||
|
||||
</menu>
|
@ -1,23 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/add_favorite_menu_button"
|
||||
android:icon="@drawable/ic_action_new"
|
||||
android:showAsAction="ifRoom|withText"
|
||||
android:title="@string/add_route">
|
||||
</item>
|
||||
android:title="@string/add_route"></item>
|
||||
<item
|
||||
android:id="@+id/view_system_map_button"
|
||||
android:icon="@drawable/ic_action_map"
|
||||
android:showAsAction="ifRoom|withText"
|
||||
android:title="@string/view_system_map">
|
||||
</item>
|
||||
android:title="@string/view_system_map"></item>
|
||||
<item
|
||||
android:id="@+id/elevator_button"
|
||||
android:icon="@drawable/ic_action_elevator"
|
||||
android:showAsAction="ifRoom|withText"
|
||||
android:title="Check elevator status">
|
||||
</item>
|
||||
android:title="Check elevator status"></item>
|
||||
|
||||
</menu>
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
|
||||
</menu>
|
@ -1,27 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/cancel_alarm_button"
|
||||
android:icon="@drawable/ic_action_cancel_alarm"
|
||||
android:showAsAction="always|withText"
|
||||
android:title="@string/cancel_alarm"
|
||||
android:visible="false"/>
|
||||
android:visible="false" />
|
||||
<item
|
||||
android:id="@+id/set_alarm_button"
|
||||
android:icon="@drawable/ic_action_alarm"
|
||||
android:showAsAction="always|withText"
|
||||
android:title="@string/set_alarm"/>
|
||||
<item
|
||||
android:id="@+id/share_arrival"
|
||||
android:icon="@drawable/ic_action_mail"
|
||||
android:showAsAction="always|withText"
|
||||
android:title="@string/share_arrival_time" />
|
||||
android:title="@string/set_alarm" />
|
||||
<item
|
||||
android:id="@+id/share_arrival"
|
||||
android:icon="@drawable/ic_action_mail"
|
||||
android:showAsAction="always|withText"
|
||||
android:title="@string/share_arrival_time" />
|
||||
<item
|
||||
android:id="@+id/delete"
|
||||
android:icon="@drawable/ic_action_delete"
|
||||
android:showAsAction="always|withText"
|
||||
android:title="@string/delete">
|
||||
</item>
|
||||
android:title="@string/delete"></item>
|
||||
|
||||
</menu>
|
@ -3,8 +3,7 @@
|
||||
|
||||
<!-- Base application theme is the default theme. -->
|
||||
|
||||
<style name="AppTheme" parent="@style/Holo.Theme">
|
||||
</style>
|
||||
<style name="AppTheme" parent="@style/Holo.Theme"></style>
|
||||
|
||||
<style name="ButtonBar">
|
||||
<item name="android:layout_width">fill_parent</item>
|
||||
|
Loading…
Reference in New Issue
Block a user