Moved boarded departure to application scope

Fixed some alert/notification issues
This commit is contained in:
Doug Keen 2012-09-18 10:11:52 -07:00
parent 5fe231abbe
commit ad6541a348
14 changed files with 365 additions and 207 deletions

View File

@ -13,6 +13,7 @@
android:targetSdkVersion="14" />
<application
android:name=".BartRunnerApplication"
android:icon="@drawable/icon"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
@ -64,10 +65,16 @@
android:exported="false"
android:label="BartRunner data provider" />
<service android:name=".NotificationService" />
<service android:name=".EtdService" />
<service
android:name=".NotificationService"
android:exported="false" />
<service
android:name=".EtdService"
android:exported="false" />
<receiver android:name=".AlarmBroadcastReceiver" >
<receiver
android:name=".AlarmBroadcastReceiver"
android:exported="false" >
<intent-filter>
<action android:name="com.dougkeen.action.ALARM" />

View File

@ -7,7 +7,7 @@
<net.simonvt.widget.NumberPicker
android:id="@+id/numberPicker"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_height="wrap_content"
android:layout_weight="1" >
</net.simonvt.widget.NumberPicker>

View File

@ -38,5 +38,7 @@
<string name="your_train">Your train</string>
<string name="skip_alert">Skip alert</string>
<string name="set_up_departure_alert">Set up departure alert</string>
<string name="train_alert_text">Your train is leaving soon!</string>
<string name="silence_alarm">Silence alarm</string>
</resources>

View File

@ -10,10 +10,12 @@ public class AlarmBroadcastReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
WakeLocker.acquire(context);
Intent targetIntent = new Intent(Intent.ACTION_VIEW, intent.getData());
targetIntent.putExtra("boardedDeparture", intent.getExtras()
.getParcelable("departure"));
targetIntent.putExtra("soundAlarm", true);
BartRunnerApplication application = (BartRunnerApplication) context
.getApplicationContext();
application.setPlayAlarmRingtone(true);
Intent targetIntent = new Intent(Intent.ACTION_VIEW, application
.getBoardedDeparture().getStationPair().getUri());
targetIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(targetIntent);

View File

@ -0,0 +1,27 @@
package com.dougkeen.bart;
import com.dougkeen.bart.model.Departure;
import android.app.Application;
public class BartRunnerApplication extends Application {
private Departure mBoardedDeparture;
private boolean playAlarmRingtone;
public boolean shouldPlayAlarmRingtone() {
return playAlarmRingtone;
}
public void setPlayAlarmRingtone(boolean playAlarmRingtone) {
this.playAlarmRingtone = playAlarmRingtone;
}
public Departure getBoardedDeparture() {
return mBoardedDeparture;
}
public void setBoardedDeparture(Departure boardedDeparture) {
this.mBoardedDeparture = boardedDeparture;
}
}

View File

@ -66,7 +66,7 @@ public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
final Departure departure = getItem(position);
((TextView) view.findViewById(R.id.destinationText)).setText(departure
.getDestination().toString());
.getTrainDestination().toString());
TimedTextSwitcher textSwitcher = (TimedTextSwitcher) view
.findViewById(R.id.trainLengthText);
@ -100,7 +100,7 @@ public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
ImageView colorBar = (ImageView) view
.findViewById(R.id.destinationColorBar);
((GradientDrawable) colorBar.getDrawable()).setColor(Color
.parseColor(departure.getDestinationColor()));
.parseColor(departure.getTrainDestinationColor()));
CountdownTextView countdownTextView = (CountdownTextView) view
.findViewById(R.id.countdown);
countdownTextView.setText(departure.getCountdownText());

View File

@ -299,7 +299,7 @@ public class EtdService extends Service {
ScheduleItem trip = mLatestScheduleInfo.getTrips().get(i);
// Definitely not a match if they have different
// destinations
if (!departure.getDestination().abbreviation.equals(trip
if (!departure.getTrainDestination().abbreviation.equals(trip
.getTrainHeadStation())) {
continue;
}
@ -419,6 +419,9 @@ public class EtdService extends Service {
boolean needsBetterAccuracy = false;
final Departure boardedDeparture = ((BartRunnerApplication) getApplication())
.getBoardedDeparture();
/*
* Keep track of first departure, since we'll request another quick
* refresh if it has departed.
@ -433,6 +436,9 @@ public class EtdService extends Service {
firstDeparture = departure;
}
mLatestDepartures.add(departure);
if (departure.equals(boardedDeparture)) {
boardedDeparture.mergeEstimate(departure);
}
}
/*
@ -494,6 +500,10 @@ public class EtdService extends Service {
if (existingDeparture.getUncertaintySeconds() > UNCERTAINTY_THRESHOLD) {
needsBetterAccuracy = true;
}
if (departure.equals(boardedDeparture)) {
boardedDeparture.mergeEstimate(departure);
}
}
}
Collections.sort(mLatestDepartures);

View File

@ -3,16 +3,19 @@ package com.dougkeen.bart;
import java.util.List;
import android.app.AlarmManager;
import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.Builder;
@ -23,13 +26,15 @@ import com.dougkeen.bart.model.Constants;
import com.dougkeen.bart.model.Departure;
import com.dougkeen.bart.model.StationPair;
public class NotificationService extends IntentService implements
EtdServiceListener {
public class NotificationService extends Service implements EtdServiceListener {
private static final int DEPARTURE_NOTIFICATION_ID = 123;
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private boolean mBound = false;
private EtdService mEtdService;
private Departure mDeparture;
private StationPair mStationPair;
private NotificationManager mNotificationManager;
private AlarmManager mAlarmManager;
@ -37,9 +42,21 @@ public class NotificationService extends IntentService implements
private PendingIntent mAlarmPendingIntent;
private int mAlertLeadTime;
private Handler mHandler;
private boolean mHasShutDown = false;
public NotificationService() {
super("BartRunnerNotificationService");
super();
}
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent) msg.obj);
}
}
private final ServiceConnection mConnection = new ServiceConnection() {
@ -61,6 +78,13 @@ public class NotificationService extends IntentService implements
@Override
public void onCreate() {
HandlerThread thread = new HandlerThread(
"BartRunnerNotificationService");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
bindService(new Intent(this, EtdService.class), mConnection,
Context.BIND_AUTO_CREATE);
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
@ -70,25 +94,46 @@ public class NotificationService extends IntentService implements
}
@Override
public void onDestroy() {
if (mBound)
unbindService(mConnection);
super.onDestroy();
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
@Override
protected void onHandleIntent(Intent intent) {
Bundle bundle = intent.getExtras();
Departure departure = (Departure) bundle.getParcelable("departure");
mStationPair = (StationPair) bundle.getParcelable("stationPair");
mAlertLeadTime = bundle.getInt("alertLeadTime");
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return START_STICKY;
}
if (mEtdService != null && mDeparture != null
&& !mDeparture.equals(departure)) {
mEtdService.unregisterListener(this);
@Override
public void onDestroy() {
shutDown(true);
if (mBound)
unbindService(mConnection);
mServiceLooper.quit();
super.onDestroy();
}
protected void onHandleIntent(Intent intent) {
final Departure boardedDeparture = ((BartRunnerApplication) getApplication())
.getBoardedDeparture();
if (boardedDeparture == null) {
// Nothing to notify about
shutDown(false);
return;
}
mDeparture = departure;
Bundle bundle = intent.getExtras();
StationPair oldStationPair = mStationPair;
mStationPair = boardedDeparture.getStationPair();
mAlertLeadTime = bundle.getInt("alertLeadTime");
if (mEtdService != null && mStationPair != null
&& !mStationPair.equals(oldStationPair)) {
mEtdService.unregisterListener(this);
}
if (getStationPair() != null && mEtdService != null) {
mEtdService.registerListener(this);
@ -98,7 +143,6 @@ public class NotificationService extends IntentService implements
Intent targetIntent = new Intent(Intent.ACTION_VIEW,
mStationPair.getUri());
targetIntent.putExtra("boardedDeparture", mDeparture);
targetIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mNotificationIntent = PendingIntent.getActivity(this, 0, targetIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
@ -111,7 +155,9 @@ public class NotificationService extends IntentService implements
private void refreshAlarmPendingIntent() {
final Intent alarmIntent = new Intent(Constants.ACTION_ALARM,
getStationPair().getUri());
alarmIntent.putExtra("departure", mDeparture);
final Departure boardedDeparture = ((BartRunnerApplication) getApplication())
.getBoardedDeparture();
alarmIntent.putExtra("departure", boardedDeparture);
mAlarmPendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
}
@ -137,7 +183,9 @@ public class NotificationService extends IntentService implements
}
private long getAlertClockTime() {
return mDeparture.getMeanEstimate() - mAlertLeadTime * 60 * 1000;
final Departure boardedDeparture = ((BartRunnerApplication) getApplication())
.getBoardedDeparture();
return boardedDeparture.getMeanEstimate() - mAlertLeadTime * 60 * 1000;
}
private void cancelAlarm() {
@ -146,15 +194,17 @@ public class NotificationService extends IntentService implements
@Override
public void onETDChanged(List<Departure> departures) {
final Departure boardedDeparture = ((BartRunnerApplication) getApplication())
.getBoardedDeparture();
for (Departure departure : departures) {
if (departure.equals(mDeparture)
&& (mDeparture.getMeanSecondsLeft() != departure
.getMeanSecondsLeft() || mDeparture
if (departure.equals(boardedDeparture)
&& (boardedDeparture.getMeanSecondsLeft() != departure
.getMeanSecondsLeft() || boardedDeparture
.getUncertaintySeconds() != departure
.getUncertaintySeconds())) {
long initialAlertClockTime = getAlertClockTime();
mDeparture.mergeEstimate(departure);
boardedDeparture.mergeEstimate(departure);
final long now = System.currentTimeMillis();
if (initialAlertClockTime > now
@ -194,8 +244,11 @@ public class NotificationService extends IntentService implements
private long mNextScheduledCheckClockTime = 0;
private void pollDepartureStatus() {
if (mDeparture.hasDeparted()) {
shutDown();
final Departure boardedDeparture = ((BartRunnerApplication) getApplication())
.getBoardedDeparture();
if (boardedDeparture.hasDeparted()) {
shutDown(false);
}
updateNotification();
@ -214,34 +267,52 @@ public class NotificationService extends IntentService implements
}
}
private void shutDown() {
mEtdService.unregisterListener(this);
mNotificationManager.cancel(DEPARTURE_NOTIFICATION_ID);
cancelAlarm();
stopSelf();
private void shutDown(boolean isBeingDestroyed) {
if (!mHasShutDown) {
mHasShutDown = true;
mEtdService.unregisterListener(this);
mNotificationManager.cancel(DEPARTURE_NOTIFICATION_ID);
cancelAlarm();
if (!isBeingDestroyed)
stopSelf();
}
}
private void updateNotification() {
Builder notificationBuilder = new NotificationCompat.Builder(this);
notificationBuilder.setOngoing(true);
notificationBuilder.setSmallIcon(R.drawable.icon);
final int minutes = mDeparture.getMeanSecondsLeft() / 60;
final String minutesText = (minutes == 0) ? "Less than one minute"
: (minutes + " minute" + ((minutes != 1) ? "s" : ""));
notificationBuilder.setContentTitle(mStationPair.getDestination().name);
notificationBuilder.setContentText(minutesText + " until departure");
notificationBuilder.setContentIntent(mNotificationIntent);
if (mHasShutDown) {
mNotificationManager.cancel(DEPARTURE_NOTIFICATION_ID);
return;
}
final Departure boardedDeparture = ((BartRunnerApplication) getApplication())
.getBoardedDeparture();
final int halfMinutes = (boardedDeparture.getMeanSecondsLeft() + 15) / 30;
float minutes = halfMinutes / 2f;
final String minutesText = (minutes < 1) ? "Less than one minute"
: (String.format("~%.1f minute", minutes) + ((minutes != 1.0) ? "s"
: ""));
Builder notificationBuilder = new NotificationCompat.Builder(this)
.setOngoing(true)
.setSmallIcon(R.drawable.icon)
.setContentTitle(
mStationPair.getOrigin().shortName + " to "
+ mStationPair.getDestination().shortName)
.setContentText(minutesText + " until departure")
.setContentIntent(mNotificationIntent);
mNotificationManager.notify(DEPARTURE_NOTIFICATION_ID,
notificationBuilder.getNotification());
}
private int getPollIntervalMillis() {
final int secondsToAlarm = mDeparture.getMeanSecondsLeft()
final Departure boardedDeparture = ((BartRunnerApplication) getApplication())
.getBoardedDeparture();
final int secondsToAlarm = boardedDeparture.getMeanSecondsLeft()
- mAlertLeadTime * 60;
if (secondsToAlarm < -20) {
/* Alarm should have already gone off by now */
shutDown();
shutDown(false);
return 10000000; // Arbitrarily large number
}
@ -255,4 +326,10 @@ public class NotificationService extends IntentService implements
return 10 * 1000;
}
}
@Override
public IBinder onBind(Intent intent) {
// Doesn't support binding
return null;
}
}

View File

@ -12,19 +12,13 @@ import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import com.WazaBe.HoloEverywhere.AlertDialog;
import com.dougkeen.bart.model.Departure;
import com.dougkeen.bart.model.StationPair;
public class TrainAlertDialogFragment extends DialogFragment {
private static final String KEY_LAST_ALERT_LEAD_TIME = "lastAlertLeadTime";
private Departure mDeparture;
private StationPair mStationPair;
public TrainAlertDialogFragment(Departure departure, StationPair stationPair) {
public TrainAlertDialogFragment() {
super();
this.mDeparture = departure;
this.mStationPair = stationPair;
}
@Override
@ -38,7 +32,11 @@ public class TrainAlertDialogFragment extends DialogFragment {
NumberPicker numberPicker = (NumberPicker) getDialog().findViewById(
R.id.numberPicker);
final int maxValue = mDeparture.getMeanSecondsLeft() / 60;
BartRunnerApplication application = (BartRunnerApplication) getActivity()
.getApplication();
final int maxValue = application.getBoardedDeparture()
.getMeanSecondsLeft() / 60;
String[] displayedValues = new String[maxValue];
for (int i = 1; i <= maxValue; i++) {
@ -84,10 +82,9 @@ public class TrainAlertDialogFragment extends DialogFragment {
alertLeadTime);
editor.commit();
Intent intent = new Intent(getActivity(),
Intent intent = new Intent(getActivity()
.getApplicationContext(),
NotificationService.class);
intent.putExtra("departure", mDeparture);
intent.putExtra("stationPair", mStationPair);
intent.putExtra("alertLeadTime", alertLeadTime);
getActivity().startService(intent);
}

View File

@ -1,12 +1,10 @@
package com.dougkeen.bart;
import java.io.IOException;
import java.util.List;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@ -15,7 +13,6 @@ import android.database.Cursor;
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.media.MediaPlayer;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
@ -64,7 +61,6 @@ public class ViewDeparturesActivity extends SherlockFragmentActivity implements
private Station mDestination;
private Departure mSelectedDeparture;
private Departure mBoardedDeparture;
private DepartureArrayAdapter mDeparturesAdapter;
@ -132,6 +128,7 @@ public class ViewDeparturesActivity extends SherlockFragmentActivity implements
if (mBound && mEtdService != null)
mEtdService
.registerListener(ViewDeparturesActivity.this);
refreshBoardedDeparture();
getSupportLoaderManager().destroyLoader(LOADER_ID);
}
@ -151,12 +148,6 @@ public class ViewDeparturesActivity extends SherlockFragmentActivity implements
mDeparturesAdapter = new DepartureArrayAdapter(this,
R.layout.departure_listing);
if (intent.getExtras() != null
&& intent.getExtras().containsKey("boardedDeparture")) {
mBoardedDeparture = (Departure) intent.getExtras().getParcelable(
"boardedDeparture");
}
if (savedInstanceState != null) {
if (savedInstanceState.containsKey("departures")) {
for (Parcelable departure : savedInstanceState
@ -165,10 +156,6 @@ public class ViewDeparturesActivity extends SherlockFragmentActivity implements
}
mDeparturesAdapter.notifyDataSetChanged();
}
if (savedInstanceState.containsKey("boardedDeparture")) {
mBoardedDeparture = (Departure) savedInstanceState
.getParcelable("boardedDeparture");
}
if (savedInstanceState.containsKey("selectedDeparture")) {
mSelectedDeparture = (Departure) savedInstanceState
.getParcelable("selectedDeparture");
@ -201,7 +188,8 @@ public class ViewDeparturesActivity extends SherlockFragmentActivity implements
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
if (intent.getBooleanExtra("soundAlarm", false)) {
if (((BartRunnerApplication) getApplication())
.shouldPlayAlarmRingtone()) {
soundTheAlarm();
}
}
@ -230,10 +218,12 @@ public class ViewDeparturesActivity extends SherlockFragmentActivity implements
}
}, 20000);
((BartRunnerApplication) getApplication()).setPlayAlarmRingtone(false);
Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Your train is leaving soon!")
builder.setMessage(R.string.train_alert_text)
.setCancelable(false)
.setNeutralButton("Silence alarm",
.setNeutralButton(R.string.silence_alarm,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
@ -316,16 +306,22 @@ public class ViewDeparturesActivity extends SherlockFragmentActivity implements
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Departure[] departures = new Departure[mDeparturesAdapter.getCount()];
for (int i = mDeparturesAdapter.getCount() - 1; i >= 0; i--) {
departures[i] = mDeparturesAdapter.getItem(i);
if (mOrigin != null || mDestination != null) {
/*
* If origin or destination are null, this thing was never
* initialized in the first place, so there's really nothing to save
*/
Departure[] departures = new Departure[mDeparturesAdapter
.getCount()];
for (int i = mDeparturesAdapter.getCount() - 1; i >= 0; i--) {
departures[i] = mDeparturesAdapter.getItem(i);
}
outState.putParcelableArray("departures", departures);
outState.putParcelable("selectedDeparture", mSelectedDeparture);
outState.putBoolean("hasActionMode", mActionMode != null);
outState.putString("origin", mOrigin.abbreviation);
outState.putString("destination", mDestination.abbreviation);
}
outState.putParcelableArray("departures", departures);
outState.putParcelable("boardedDeparture", mBoardedDeparture);
outState.putParcelable("selectedDeparture", mSelectedDeparture);
outState.putBoolean("hasActionMode", mActionMode != null);
outState.putString("origin", mOrigin.abbreviation);
outState.putString("destination", mDestination.abbreviation);
}
@Override
@ -383,28 +379,33 @@ public class ViewDeparturesActivity extends SherlockFragmentActivity implements
}
private void refreshBoardedDeparture() {
if (mBoardedDeparture == null)
final Departure boardedDeparture = ((BartRunnerApplication) getApplication())
.getBoardedDeparture();
if (boardedDeparture == null
|| boardedDeparture.getStationPair() == null
|| !boardedDeparture.getStationPair().equals(getStationPair())) {
findViewById(R.id.yourTrainSection).setVisibility(View.GONE);
return;
}
final Departure departure = mBoardedDeparture;
findViewById(R.id.yourTrainSection).setVisibility(View.VISIBLE);
((TextView) findViewById(R.id.yourTrainDestinationText))
.setText(departure.getDestination().toString());
.setText(boardedDeparture.getTrainDestination().toString());
((TextView) findViewById(R.id.yourTrainTrainLengthText))
.setText(departure.getTrainLengthText());
.setText(boardedDeparture.getTrainLengthText());
ImageView colorBar = (ImageView) findViewById(R.id.yourTrainDestinationColorBar);
((GradientDrawable) colorBar.getDrawable()).setColor(Color
.parseColor(departure.getDestinationColor()));
if (departure.isBikeAllowed()) {
.parseColor(boardedDeparture.getTrainDestinationColor()));
if (boardedDeparture.isBikeAllowed()) {
((ImageView) findViewById(R.id.yourTrainBikeIcon))
.setVisibility(View.VISIBLE);
} else {
((ImageView) findViewById(R.id.yourTrainBikeIcon))
.setVisibility(View.INVISIBLE);
}
if (departure.getRequiresTransfer()) {
if (boardedDeparture.getRequiresTransfer()) {
((ImageView) findViewById(R.id.yourTrainXferIcon))
.setVisibility(View.VISIBLE);
} else {
@ -414,26 +415,27 @@ public class ViewDeparturesActivity extends SherlockFragmentActivity implements
CountdownTextView departureCountdown = (CountdownTextView) findViewById(R.id.yourTrainDepartureCountdown);
CountdownTextView arrivalCountdown = (CountdownTextView) findViewById(R.id.yourTrainArrivalCountdown);
departureCountdown.setText("Leaves in " + departure.getCountdownText()
+ " " + departure.getUncertaintyText());
departureCountdown.setText("Leaves in "
+ boardedDeparture.getCountdownText() + " "
+ boardedDeparture.getUncertaintyText());
departureCountdown.setTextProvider(new TextProvider() {
@Override
public String getText(long tickNumber) {
if (departure.hasDeparted()) {
if (boardedDeparture.hasDeparted()) {
return "Departed";
} else {
return "Leaves in " + departure.getCountdownText() + " "
+ departure.getUncertaintyText();
return "Leaves in " + boardedDeparture.getCountdownText()
+ " " + boardedDeparture.getUncertaintyText();
}
}
});
arrivalCountdown.setText(departure
arrivalCountdown.setText(boardedDeparture
.getEstimatedArrivalMinutesLeftText(this));
arrivalCountdown.setTextProvider(new TextProvider() {
@Override
public String getText(long tickNumber) {
return departure
return boardedDeparture
.getEstimatedArrivalMinutesLeftText(ViewDeparturesActivity.this);
}
});
@ -441,7 +443,7 @@ public class ViewDeparturesActivity extends SherlockFragmentActivity implements
private void startDepartureActionMode() {
mActionMode = startActionMode(new DepartureActionMode());
mActionMode.setTitle(mSelectedDeparture.getDestinationName());
mActionMode.setTitle(mSelectedDeparture.getTrainDestinationName());
mActionMode.setSubtitle(mSelectedDeparture.getTrainLengthText());
}
@ -461,14 +463,19 @@ public class ViewDeparturesActivity extends SherlockFragmentActivity implements
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
if (item.getItemId() == R.id.boardTrain) {
mBoardedDeparture = mSelectedDeparture;
final BartRunnerApplication application = (BartRunnerApplication) getApplication();
mSelectedDeparture.setPassengerDestination(mDestination);
application.setBoardedDeparture(mSelectedDeparture);
refreshBoardedDeparture();
// Stop the notification service
/*stopService(new Intent(getApplicationContext(),
NotificationService.class));*/
// Don't prompt for alert if train is about to leave
if (mBoardedDeparture.getMeanSecondsLeft() / 60 > 1) {
new TrainAlertDialogFragment(mBoardedDeparture,
getStationPair()).show(getSupportFragmentManager(),
"dialog");
if (mSelectedDeparture.getMeanSecondsLeft() / 60 > 1) {
new TrainAlertDialogFragment().show(
getSupportFragmentManager(), "dialog");
}
mode.finish();
@ -531,15 +538,8 @@ public class ViewDeparturesActivity extends SherlockFragmentActivity implements
}
}
if (mBoardedDeparture != null) {
for (Departure departure : departures) {
if (departure.equals(mBoardedDeparture)) {
mBoardedDeparture.mergeEstimate(departure);
refreshBoardedDeparture();
break;
}
}
}
refreshBoardedDeparture();
getListAdapter().notifyDataSetChanged();
}
}

View File

@ -20,7 +20,7 @@ public class Departure implements Parcelable, Comparable<Departure> {
String platform, String direction, boolean bikeAllowed,
String trainLength, int minutes) {
super();
this.destination = Station.getByAbbreviation(destinationAbbr);
this.trainDestination = Station.getByAbbreviation(destinationAbbr);
this.destinationColor = destinationColor;
this.platform = platform;
this.direction = direction;
@ -34,7 +34,8 @@ public class Departure implements Parcelable, Comparable<Departure> {
}
private Station origin;
private Station destination;
private Station trainDestination;
private Station passengerDestination;
private Line line;
private String destinationColor;
private String platform;
@ -63,26 +64,42 @@ public class Departure implements Parcelable, Comparable<Departure> {
this.origin = origin;
}
public Station getDestination() {
return destination;
public Station getTrainDestination() {
return trainDestination;
}
public void setDestination(Station destination) {
this.destination = destination;
public void setTrainDestination(Station destination) {
this.trainDestination = destination;
}
public String getDestinationName() {
if (destination != null)
return destination.name;
public String getTrainDestinationName() {
if (trainDestination != null)
return trainDestination.name;
return null;
}
public String getDestinationAbbreviation() {
if (destination != null)
return destination.abbreviation;
public String getTrainDestinationAbbreviation() {
if (trainDestination != null)
return trainDestination.abbreviation;
return null;
}
public Station getPassengerDestination() {
return passengerDestination;
}
public void setPassengerDestination(Station passengerDestination) {
this.passengerDestination = passengerDestination;
}
public StationPair getStationPair() {
if (passengerDestination != null) {
return new StationPair(origin, passengerDestination);
} else {
return null;
}
}
public Line getLine() {
return line;
}
@ -91,11 +108,11 @@ public class Departure implements Parcelable, Comparable<Departure> {
this.line = line;
}
public String getDestinationColor() {
public String getTrainDestinationColor() {
return destinationColor;
}
public void setDestinationColor(String destinationColor) {
public void setTrainDestinationColor(String destinationColor) {
this.destinationColor = destinationColor;
}
@ -347,8 +364,9 @@ public class Departure implements Parcelable, Comparable<Departure> {
final int prime = 31;
int result = 1;
result = prime * result + (bikeAllowed ? 1231 : 1237);
result = prime * result
+ ((destination == null) ? 0 : destination.hashCode());
result = prime
* result
+ ((trainDestination == null) ? 0 : trainDestination.hashCode());
result = prime
* result
+ ((destinationColor == null) ? 0 : destinationColor.hashCode());
@ -377,7 +395,7 @@ public class Departure implements Parcelable, Comparable<Departure> {
Departure other = (Departure) obj;
if (bikeAllowed != other.bikeAllowed)
return false;
if (destination != other.destination)
if (trainDestination != other.trainDestination)
return false;
if (destinationColor == null) {
if (other.destinationColor != null)
@ -446,7 +464,7 @@ public class Departure implements Parcelable, Comparable<Departure> {
public String toString() {
java.text.DateFormat format = SimpleDateFormat.getTimeInstance();
StringBuilder builder = new StringBuilder();
builder.append(destination);
builder.append(trainDestination);
if (requiresTransfer) {
builder.append(" (w/ xfer)");
}
@ -463,7 +481,9 @@ public class Departure implements Parcelable, Comparable<Departure> {
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(origin.abbreviation);
dest.writeString(destination.abbreviation);
dest.writeString(trainDestination.abbreviation);
dest.writeString(passengerDestination == null ? null
: passengerDestination.abbreviation);
dest.writeString(destinationColor);
dest.writeString(platform);
dest.writeString(direction);
@ -482,7 +502,8 @@ public class Departure implements Parcelable, Comparable<Departure> {
private void readFromParcel(Parcel in) {
origin = Station.getByAbbreviation(in.readString());
destination = Station.getByAbbreviation(in.readString());
trainDestination = Station.getByAbbreviation(in.readString());
passengerDestination = Station.getByAbbreviation(in.readString());
destinationColor = in.readString();
platform = in.readString();
direction = in.readString();

View File

@ -83,7 +83,7 @@ public class RealTimeDepartures {
private void addDepartureIfApplicable(Departure departure) {
Station destination = Station.getByAbbreviation(departure
.getDestinationAbbreviation());
.getTrainDestinationAbbreviation());
if (departure.getLine() == null)
return;
for (Route route : routes) {
@ -118,7 +118,7 @@ public class RealTimeDepartures {
Departure departure = iterator.next();
if (departure.getRequiresTransfer()
&& (!departure.isTransferScheduled() || departure
.getDestination().isBetween(getOrigin(),
.getTrainDestination().isBetween(getOrigin(),
getDestination(), departure.getLine()))) {
iterator.remove();
}

View File

@ -7,55 +7,68 @@ import java.util.List;
import android.util.Log;
public enum Station {
_12TH("12th", "12th St./Oakland City Center", false, false, "bayf", "bayf"),
_16TH("16th", "16th St. Mission", false, false),
_19TH("19th", "19th St./Oakland", false, false, "bayf", "bayf"),
_24TH("24th", "24th St. Mission", false, false),
ASHB("ashb", "Ashby", false, false, "mcar", "mcar"),
BALB("balb", "Balboa Park", false, false),
BAYF("bayf", "Bay Fair", true, false, "mcar", "mcar"),
CAST("cast", "Castro Valley", false, false, "bayf", "bayf"),
CIVC("civc", "Civic Center", false, false),
COLS("cols", "Coliseum/Oakland Airport", true, false, "mcar", "mcar"),
COLM("colm", "Colma", false, false, "balb", "balb"),
CONC("conc", "Concord", false, false, "mcar", "mcar"),
DALY("daly", "Daly City", false, false),
DBRK("dbrk", "Downtown Berkeley", false, false, "mcar", "mcar"),
DUBL("dubl", "Dublin/Pleasanton", false, true, "bayf", "bayf", true, 719999),
DELN("deln", "El Cerrito del Norte", false, false, "mcar", "mcar"),
PLZA("plza", "El Cerrito Plaza", false, false, "mcar", "mcar"),
EMBR("embr", "Embarcadero", false, false),
FRMT("frmt", "Fremont", true, true, "bayf", "bayf", true, 299999),
FTVL("ftvl", "Fruitvale", true, false, "mcar", "mcar"),
GLEN("glen", "Glen Park", false, false),
HAYW("hayw", "Hayward", true, false, "bayf", "bayf"),
LAFY("lafy", "Lafayette", false, false, "mcar", "mcar"),
LAKE("lake", "Lake Merritt", true, false, "mcar", "mcar"),
MCAR("mcar", "MacArthur", false, false, "bayf", "bayf"),
MLBR("mlbr", "Millbrae", false, true, "balb", "balb", true, 719999),
MONT("mont", "Montgomery St.", false, false),
NBRK("nbrk", "North Berkeley", false, false, "mcar", "mcar"),
NCON("ncon", "North Concord/Martinez", false, false, "mcar", "mcar"),
ORIN("orin", "Orinda", false, false, "mcar", "mcar"),
PITT("pitt", "Pittsburg/Bay Point", false, true, "mcar", "mcar", true,
_12TH("12th", "12th St./Oakland City Center", "12th St Oak", false, false,
"bayf", "bayf"),
_16TH("16th", "16th St. Mission", "16th St", false, false),
_19TH("19th", "19th St./Oakland", "19th St Oak", false, false, "bayf",
"bayf"),
_24TH("24th", "24th St. Mission", "24th St", false, false),
ASHB("ashb", "Ashby", "Ashby", false, false, "mcar", "mcar"),
BALB("balb", "Balboa Park", "Balboa", false, false),
BAYF("bayf", "Bay Fair", "Bay Fair", true, false, "mcar", "mcar"),
CAST("cast", "Castro Valley", "Castro Vly", false, false, "bayf", "bayf"),
CIVC("civc", "Civic Center", "Civic Ctr", false, false),
COLS("cols", "Coliseum/Oakland Airport", "Coliseum/OAK", true, false,
"mcar", "mcar"),
COLM("colm", "Colma", "Colma", false, false, "balb", "balb"),
CONC("conc", "Concord", "Concord", false, false, "mcar", "mcar"),
DALY("daly", "Daly City", "Daly City", false, false),
DBRK("dbrk", "Downtown Berkeley", "Dtwn Berk", false, false, "mcar",
"mcar"),
DUBL("dubl", "Dublin/Pleasanton", "Dbln/Plsntn", false, true, "bayf",
"bayf", true, 719999),
DELN("deln", "El Cerrito del Norte", "El Cer/Norte", false, false, "mcar",
"mcar"),
PLZA("plza", "El Cerrito Plaza", "El Cer/Plz", false, false, "mcar", "mcar"),
EMBR("embr", "Embarcadero", "Embarcdro", false, false),
FRMT("frmt", "Fremont", "Fremont", true, true, "bayf", "bayf", true, 299999),
FTVL("ftvl", "Fruitvale", "Fruitvale", true, false, "mcar", "mcar"),
GLEN("glen", "Glen Park", "Glen Park", false, false),
HAYW("hayw", "Hayward", "Hayward", true, false, "bayf", "bayf"),
LAFY("lafy", "Lafayette", "Lafayette", false, false, "mcar", "mcar"),
LAKE("lake", "Lake Merritt", "Lk Merritt", true, false, "mcar", "mcar"),
MCAR("mcar", "MacArthur", "MacArthur", false, false, "bayf", "bayf"),
MLBR("mlbr", "Millbrae", "Millbrae", false, true, "balb", "balb", true,
719999),
PHIL("phil", "Pleasant Hill", false, false, "mcar", "mcar"),
POWL("powl", "Powell St.", false, false),
RICH("rich", "Richmond", false, true, "mcar", "mcar", true, 299999),
ROCK("rock", "Rockridge", false, false, "mcar", "mcar"),
SBRN("sbrn", "San Bruno", false, false, "balb", "balb"),
SANL("sanl", "San Leandro", true, false, "mcar", "mcar"),
SFIA("sfia", "SFO Airport", false, false, "balb", "balb", true, 719999),
SHAY("shay", "South Hayward", true, false, "bayf", "bayf"),
SSAN("ssan", "South San Francisco", false, false, "balb", "balb"),
UCTY("ucty", "Union City", true, false, "bayf", "bayf"),
WCRK("wcrk", "Walnut Creek", false, false, "mcar", "mcar"),
WDUB("wdub", "West Dublin/Pleasanton", false, false, "bayf", "bayf"),
WOAK("woak", "West Oakland", false, false),
SPCL("spcl", "Special", false, false);
MONT("mont", "Montgomery St.", "Montgomery", false, false),
NBRK("nbrk", "North Berkeley", "N Berkeley", false, false, "mcar", "mcar"),
NCON("ncon", "North Concord/Martinez", "N Conc/Mrtnz", false, false,
"mcar", "mcar"),
ORIN("orin", "Orinda", "Orinda", false, false, "mcar", "mcar"),
PITT("pitt", "Pittsburg/Bay Point", "Pitt/Bay Pt", false, true, "mcar",
"mcar", true, 719999),
PHIL("phil", "Pleasant Hill", "Plsnt Hill", false, false, "mcar", "mcar"),
POWL("powl", "Powell St.", "Powell", false, false),
RICH("rich", "Richmond", "Richmond", false, true, "mcar", "mcar", true,
299999),
ROCK("rock", "Rockridge", "Rockridge", false, false, "mcar", "mcar"),
SBRN("sbrn", "San Bruno", "San Bruno", false, false, "balb", "balb"),
SANL("sanl", "San Leandro", "San Leandro", true, false, "mcar", "mcar"),
SFIA("sfia", "SFO Airport", "SFO", false, false, "balb", "balb", true,
719999),
SHAY("shay", "South Hayward", "S Hayward", true, false, "bayf", "bayf"),
SSAN("ssan", "South San Francisco", "S San Fran", false, false, "balb",
"balb"),
UCTY("ucty", "Union City", "Union City", true, false, "bayf", "bayf"),
WCRK("wcrk", "Walnut Creek", "Walnut Crk", false, false, "mcar", "mcar"),
WDUB("wdub", "West Dublin/Pleasanton", "W Dbln/Plsntn", false, false,
"bayf", "bayf"),
WOAK("woak", "West Oakland", "W Oakland", false, false),
SPCL("spcl", "Special", "Special", false, false);
public final String abbreviation;
public final String name;
public final String shortName;
public final boolean transferFriendly;
public final boolean invertDirection;
protected final String inboundTransferStation;
@ -66,32 +79,34 @@ public enum Station {
public final static int DEFAULT_DEPARTURE_EQUALITY_TOLERANCE = 119999;
private Station(String abbreviation, String name, boolean invertDirection,
boolean endOfLine) {
this(abbreviation, name, invertDirection, endOfLine, null, null, false,
DEFAULT_DEPARTURE_EQUALITY_TOLERANCE);
}
private Station(String abbreviation, String name, boolean invertDirection,
boolean endOfLine, String transferStation) {
this(abbreviation, name, invertDirection, endOfLine, transferStation,
private Station(String abbreviation, String name, String shortName,
boolean invertDirection, boolean endOfLine) {
this(abbreviation, name, shortName, invertDirection, endOfLine, null,
null, false, DEFAULT_DEPARTURE_EQUALITY_TOLERANCE);
}
private Station(String abbreviation, String name, boolean invertDirection,
boolean endOfLine, String inboundTransferStation,
String outboundTransferStation) {
this(abbreviation, name, invertDirection, endOfLine,
private Station(String abbreviation, String name, String shortName,
boolean invertDirection, boolean endOfLine, String transferStation) {
this(abbreviation, name, shortName, invertDirection, endOfLine,
transferStation, null, false,
DEFAULT_DEPARTURE_EQUALITY_TOLERANCE);
}
private Station(String abbreviation, String name, String shortName,
boolean invertDirection, boolean endOfLine,
String inboundTransferStation, String outboundTransferStation) {
this(abbreviation, name, shortName, invertDirection, endOfLine,
inboundTransferStation, outboundTransferStation, false,
DEFAULT_DEPARTURE_EQUALITY_TOLERANCE);
}
private Station(String abbreviation, String name, boolean invertDirection,
boolean endOfLine, String inboundTransferStation,
String outboundTransferStation, boolean longStationLinger,
int departureEqualityTolerance) {
private Station(String abbreviation, String name, String shortName,
boolean invertDirection, boolean endOfLine,
String inboundTransferStation, String outboundTransferStation,
boolean longStationLinger, int departureEqualityTolerance) {
this.abbreviation = abbreviation;
this.name = name;
this.shortName = shortName;
this.invertDirection = invertDirection;
this.inboundTransferStation = inboundTransferStation;
this.transferFriendly = outboundTransferStation != null;

View File

@ -57,7 +57,7 @@ public class EtdContentHandler extends DefaultHandler {
}
if (localName.equals("estimate")) {
currentDeparture = new Departure();
currentDeparture.setDestination(Station
currentDeparture.setTrainDestination(Station
.getByAbbreviation(currentDestination));
currentDeparture.setOrigin(realTimeDepartures.getOrigin());
}
@ -89,7 +89,7 @@ public class EtdContentHandler extends DefaultHandler {
if (currentValue.equalsIgnoreCase("WHITE")) {
for (Line line : Line.values()) {
if (line.stations.indexOf(currentDeparture
.getDestination()) >= 0
.getTrainDestination()) >= 0
&& line.stations.indexOf(realTimeDepartures
.getDestination()) >= 0) {
currentDeparture.setLine(line);
@ -104,7 +104,7 @@ public class EtdContentHandler extends DefaultHandler {
+ "'");
}
} else if (localName.equals("hexcolor")) {
currentDeparture.setDestinationColor("#ff"
currentDeparture.setTrainDestinationColor("#ff"
+ currentValue.substring(1));
} else if (localName.equals("bikeflag")) {
currentDeparture.setBikeAllowed(currentValue.equalsIgnoreCase("1"));