From ad6541a3486b2f3395b7e5ee60b3784848a7f7f8 Mon Sep 17 00:00:00 2001 From: Doug Keen Date: Tue, 18 Sep 2012 10:11:52 -0700 Subject: [PATCH] Moved boarded departure to application scope Fixed some alert/notification issues --- AndroidManifest.xml | 13 +- res/layout/train_alert_dialog.xml | 2 +- res/values/strings.xml | 2 + .../dougkeen/bart/AlarmBroadcastReceiver.java | 10 +- .../dougkeen/bart/BartRunnerApplication.java | 27 +++ .../dougkeen/bart/DepartureArrayAdapter.java | 4 +- src/com/dougkeen/bart/EtdService.java | 12 +- .../dougkeen/bart/NotificationService.java | 163 +++++++++++++----- .../bart/TrainAlertDialogFragment.java | 19 +- .../dougkeen/bart/ViewDeparturesActivity.java | 110 ++++++------ src/com/dougkeen/bart/model/Departure.java | 61 ++++--- .../bart/model/RealTimeDepartures.java | 4 +- src/com/dougkeen/bart/model/Station.java | 139 ++++++++------- .../bart/networktasks/EtdContentHandler.java | 6 +- 14 files changed, 365 insertions(+), 207 deletions(-) create mode 100644 src/com/dougkeen/bart/BartRunnerApplication.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 7ed173a..7aefb2d 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -13,6 +13,7 @@ android:targetSdkVersion="14" /> @@ -64,10 +65,16 @@ android:exported="false" android:label="BartRunner data provider" /> - - + + - + diff --git a/res/layout/train_alert_dialog.xml b/res/layout/train_alert_dialog.xml index 954bbd7..60d9e9e 100644 --- a/res/layout/train_alert_dialog.xml +++ b/res/layout/train_alert_dialog.xml @@ -7,7 +7,7 @@ diff --git a/res/values/strings.xml b/res/values/strings.xml index 9343681..52e1ee3 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -38,5 +38,7 @@ Your train Skip alert Set up departure alert + Your train is leaving soon! + Silence alarm \ No newline at end of file diff --git a/src/com/dougkeen/bart/AlarmBroadcastReceiver.java b/src/com/dougkeen/bart/AlarmBroadcastReceiver.java index 9f140db..b1b369f 100644 --- a/src/com/dougkeen/bart/AlarmBroadcastReceiver.java +++ b/src/com/dougkeen/bart/AlarmBroadcastReceiver.java @@ -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); diff --git a/src/com/dougkeen/bart/BartRunnerApplication.java b/src/com/dougkeen/bart/BartRunnerApplication.java new file mode 100644 index 0000000..4e6c6d6 --- /dev/null +++ b/src/com/dougkeen/bart/BartRunnerApplication.java @@ -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; + } +} \ No newline at end of file diff --git a/src/com/dougkeen/bart/DepartureArrayAdapter.java b/src/com/dougkeen/bart/DepartureArrayAdapter.java index 7e24629..9d8bc1d 100644 --- a/src/com/dougkeen/bart/DepartureArrayAdapter.java +++ b/src/com/dougkeen/bart/DepartureArrayAdapter.java @@ -66,7 +66,7 @@ public class DepartureArrayAdapter extends ArrayAdapter { 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 { 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()); diff --git a/src/com/dougkeen/bart/EtdService.java b/src/com/dougkeen/bart/EtdService.java index d0753d8..fea62d7 100644 --- a/src/com/dougkeen/bart/EtdService.java +++ b/src/com/dougkeen/bart/EtdService.java @@ -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); diff --git a/src/com/dougkeen/bart/NotificationService.java b/src/com/dougkeen/bart/NotificationService.java index 223c6fb..4d3a6f3 100644 --- a/src/com/dougkeen/bart/NotificationService.java +++ b/src/com/dougkeen/bart/NotificationService.java @@ -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 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; + } } diff --git a/src/com/dougkeen/bart/TrainAlertDialogFragment.java b/src/com/dougkeen/bart/TrainAlertDialogFragment.java index 13604b2..5b9c353 100644 --- a/src/com/dougkeen/bart/TrainAlertDialogFragment.java +++ b/src/com/dougkeen/bart/TrainAlertDialogFragment.java @@ -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); } diff --git a/src/com/dougkeen/bart/ViewDeparturesActivity.java b/src/com/dougkeen/bart/ViewDeparturesActivity.java index fdca8a1..ffff4f8 100644 --- a/src/com/dougkeen/bart/ViewDeparturesActivity.java +++ b/src/com/dougkeen/bart/ViewDeparturesActivity.java @@ -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(); } } diff --git a/src/com/dougkeen/bart/model/Departure.java b/src/com/dougkeen/bart/model/Departure.java index 0f79e4c..6d6b22d 100644 --- a/src/com/dougkeen/bart/model/Departure.java +++ b/src/com/dougkeen/bart/model/Departure.java @@ -20,7 +20,7 @@ public class Departure implements Parcelable, Comparable { 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 { } 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 { 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 { 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 { 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 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 { 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 { 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 { 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(); diff --git a/src/com/dougkeen/bart/model/RealTimeDepartures.java b/src/com/dougkeen/bart/model/RealTimeDepartures.java index 8a4495c..9513dbf 100644 --- a/src/com/dougkeen/bart/model/RealTimeDepartures.java +++ b/src/com/dougkeen/bart/model/RealTimeDepartures.java @@ -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(); } diff --git a/src/com/dougkeen/bart/model/Station.java b/src/com/dougkeen/bart/model/Station.java index 3368d5e..3309e56 100644 --- a/src/com/dougkeen/bart/model/Station.java +++ b/src/com/dougkeen/bart/model/Station.java @@ -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; diff --git a/src/com/dougkeen/bart/networktasks/EtdContentHandler.java b/src/com/dougkeen/bart/networktasks/EtdContentHandler.java index 0ca3054..d8d7e49 100644 --- a/src/com/dougkeen/bart/networktasks/EtdContentHandler.java +++ b/src/com/dougkeen/bart/networktasks/EtdContentHandler.java @@ -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"));