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