Death to tabs! Long live spaces!

This commit is contained in:
Doug Keen 2015-08-11 18:56:23 -07:00
parent 9285836e61
commit 00faa9ec76
66 changed files with 5526 additions and 5546 deletions

View File

@ -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" />

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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));
}
}

View File

@ -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());
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}
}

View File

@ -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();
}
};
}

View File

@ -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));
}
}

View File

@ -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;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
app = (BartRunnerApplication) context.getApplicationContext();
}
private BartRunnerApplication app;
@Override
public void onCreate(SQLiteDatabase db) {
}
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
app = (BartRunnerApplication) context.getApplicationContext();
}
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 onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.beginTransaction();
try {
createFavoritesTable(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() + ");");
}
Cursor query = db.query(FAVORITES_TABLE_NAME, RoutesColumns.all(),
null, null, null, null, null);
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.beginTransaction();
try {
createFavoritesTable(db);
List<StationPair> favorites = new ArrayList<StationPair>();
Cursor query = db.query(FAVORITES_TABLE_NAME, RoutesColumns.all(),
null, null, null, null, null);
while (query.moveToNext()) {
favorites.add(StationPair.createFromCursor(query));
}
List<StationPair> favorites = new ArrayList<StationPair>();
query.close();
while (query.moveToNext()) {
favorites.add(StationPair.createFromCursor(query));
}
new FavoritesPersistence(app).persist(favorites);
query.close();
db.execSQL("DROP TABLE " + FAVORITES_TABLE_NAME);
new FavoritesPersistence(app).persist(favorites);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
db.execSQL("DROP TABLE " + FAVORITES_TABLE_NAME);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
}

View File

@ -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);
}
}
});
}
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);
}
uncertaintySwitcher.setTextProvider(new TextProvider() {
@Override
public String getText(long tickNumber) {
if (tickNumber % 4 == 0) {
return departure.getUncertaintyText();
} else {
return departure
.getEstimatedDepartureTimeText(getContext(), false);
}
}
});
}
return view;
}
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);
}
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);
}
});
return view;
}
textSwitcher.setInAnimation(AnimationUtils.loadAnimation(
getContext(), android.R.anim.slide_in_left));
textSwitcher.setOutAnimation(AnimationUtils.loadAnimation(
getContext(), android.R.anim.slide_out_right));
}
}
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));
}
}
}

View File

@ -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;
}
}
}

View File

@ -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>();
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

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

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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));
}
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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];
}
};
}

View File

@ -3,6 +3,6 @@ package com.dougkeen.bart.model;
public interface TextProvider {
String getText(long tickNumber);
String getText(long tickNumber);
}

View File

@ -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);
}
}
}
}
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}
}
}

View File

@ -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();
}
}

View File

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

View File

@ -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);
}
}
}
}

View File

@ -2,5 +2,5 @@ package com.dougkeen.util;
public interface Observer<T> {
void onUpdate(final T newValue);
void onUpdate(final T newValue);
}

View File

@ -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;
}
}

View File

@ -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" />

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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