Reorganize the your_train and departure_listing layouts (and corresponding custom views) for easier editing, greater flexibility for different screens, and to fix a layout bug that was introduced when updating the libraries where the "Your Train" section would be too wide.
General code cleanup, warnings fixes, and readability improvements.
This commit is contained in:
parent
4ee80b3f90
commit
2481f0c229
@ -17,6 +17,7 @@ import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcelable;
|
||||
import android.os.Vibrator;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.view.ActionMode;
|
||||
import android.text.format.DateFormat;
|
||||
@ -48,6 +49,7 @@ import com.dougkeen.bart.services.EtdService;
|
||||
import com.dougkeen.bart.services.EtdService.EtdServiceBinder;
|
||||
import com.dougkeen.bart.services.EtdService.EtdServiceListener;
|
||||
import com.dougkeen.bart.services.EtdService_;
|
||||
import com.dougkeen.util.Assert;
|
||||
import com.dougkeen.util.Observer;
|
||||
import com.dougkeen.util.WakeLocker;
|
||||
|
||||
@ -86,8 +88,7 @@ public class ViewDeparturesActivity extends AppCompatActivity implements
|
||||
|
||||
mProgress = (ProgressBar) findViewById(android.R.id.progress);
|
||||
|
||||
mDeparturesAdapter = new DepartureArrayAdapter(this,
|
||||
R.layout.departure_listing);
|
||||
mDeparturesAdapter = new DepartureArrayAdapter(this);
|
||||
|
||||
setListAdapter(mDeparturesAdapter);
|
||||
final ListView listView = getListView();
|
||||
@ -127,9 +128,9 @@ public class ViewDeparturesActivity extends AppCompatActivity implements
|
||||
}
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
if (savedInstanceState.containsKey("departures")) {
|
||||
for (Parcelable departure : savedInstanceState
|
||||
.getParcelableArray("departures")) {
|
||||
Parcelable[] departuresArray = savedInstanceState.getParcelableArray("departures");
|
||||
if (departuresArray != null) {
|
||||
for (Parcelable departure : departuresArray) {
|
||||
mDeparturesAdapter.add((Departure) departure);
|
||||
}
|
||||
mDeparturesAdapter.notifyDataSetChanged();
|
||||
@ -151,8 +152,9 @@ public class ViewDeparturesActivity extends AppCompatActivity implements
|
||||
}
|
||||
refreshBoardedDeparture(false);
|
||||
|
||||
getSupportActionBar().setHomeButtonEnabled(true);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
ActionBar supportActionBar = Assert.notNull(getSupportActionBar());
|
||||
supportActionBar.setHomeButtonEnabled(true);
|
||||
supportActionBar.setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
if (bartRunnerApplication.shouldPlayAlarmRingtone()) {
|
||||
soundTheAlarm();
|
||||
@ -440,7 +442,7 @@ public class ViewDeparturesActivity extends AppCompatActivity implements
|
||||
return;
|
||||
}
|
||||
|
||||
mYourTrainSection.updateFromBoardedDeparture();
|
||||
mYourTrainSection.updateFromBoardedDeparture(boardedDeparture);
|
||||
|
||||
if (currentVisibility != View.VISIBLE) {
|
||||
showYourTrainSection(animate);
|
||||
|
@ -0,0 +1,46 @@
|
||||
package com.dougkeen.bart.controls;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.widget.LinearLayoutCompat;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.Checkable;
|
||||
|
||||
import com.dougkeen.bart.R;
|
||||
|
||||
/**
|
||||
* A {@link android.widget.LinearLayout} that implements {@link Checkable} and changes
|
||||
* its background color when checked.
|
||||
*/
|
||||
public class CheckableLinearLayout extends LinearLayoutCompat implements Checkable {
|
||||
|
||||
private boolean mChecked;
|
||||
|
||||
public CheckableLinearLayout(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public CheckableLinearLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public CheckableLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return mChecked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChecked(boolean checked) {
|
||||
mChecked = checked;
|
||||
int colorRes = isChecked() ? R.color.blue_selection : android.R.color.transparent;
|
||||
setBackgroundResource(colorRes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggle() {
|
||||
setChecked(!isChecked());
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package com.dougkeen.bart.controls;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.widget.Checkable;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import com.dougkeen.bart.R;
|
||||
|
||||
public class DepartureListItemLayout extends RelativeLayout implements
|
||||
Checkable {
|
||||
|
||||
public DepartureListItemLayout(Context context) {
|
||||
super(context);
|
||||
LayoutInflater.from(context).inflate(R.layout.departure_listing, this,
|
||||
true);
|
||||
}
|
||||
|
||||
private boolean mChecked;
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return mChecked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChecked(boolean checked) {
|
||||
mChecked = checked;
|
||||
if (isChecked()) {
|
||||
setBackgroundDrawable(getContext().getResources().getDrawable(
|
||||
R.color.blue_selection));
|
||||
} else {
|
||||
setBackgroundDrawable(getContext().getResources().getDrawable(
|
||||
android.R.color.transparent));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggle() {
|
||||
setChecked(!isChecked());
|
||||
}
|
||||
}
|
@ -10,8 +10,7 @@ import android.widget.TextSwitcher;
|
||||
import com.dougkeen.bart.R;
|
||||
import com.dougkeen.bart.model.TextProvider;
|
||||
|
||||
public class TimedTextSwitcher extends TextSwitcher implements
|
||||
Ticker.TickSubscriber {
|
||||
public class TimedTextSwitcher extends TextSwitcher implements Ticker.TickSubscriber {
|
||||
|
||||
public TimedTextSwitcher(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
@ -2,41 +2,51 @@ package com.dougkeen.bart.controls;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Checkable;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.dougkeen.bart.BartRunnerApplication;
|
||||
import com.dougkeen.bart.R;
|
||||
import com.dougkeen.bart.model.Departure;
|
||||
import com.dougkeen.bart.model.TextProvider;
|
||||
import com.dougkeen.util.Observer;
|
||||
|
||||
public class YourTrainLayout extends RelativeLayout implements Checkable {
|
||||
public class YourTrainLayout extends FrameLayout implements Checkable {
|
||||
|
||||
private final TextView destinationText;
|
||||
private final TextView trainLength;
|
||||
private final View colorBar;
|
||||
private final ImageView bikeIcon;
|
||||
private final View xferIcon;
|
||||
private final CountdownTextView departureCountdown;
|
||||
private final CountdownTextView arrivalCountdown;
|
||||
private final TextView alarmText;
|
||||
|
||||
public YourTrainLayout(Context context) {
|
||||
super(context);
|
||||
assignLayout(context);
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public YourTrainLayout(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public YourTrainLayout(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
assignLayout(context);
|
||||
}
|
||||
|
||||
public YourTrainLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
assignLayout(context);
|
||||
}
|
||||
|
||||
public void assignLayout(Context context) {
|
||||
LayoutInflater.from(context).inflate(R.layout.your_train, this, true);
|
||||
|
||||
destinationText = (TextView) findViewById(R.id.yourTrainDestinationText);
|
||||
trainLength = (TextView) findViewById(R.id.yourTrainTrainLengthText);
|
||||
colorBar = findViewById(R.id.yourTrainDestinationColorBar);
|
||||
bikeIcon = (ImageView) findViewById(R.id.yourTrainBikeIcon);
|
||||
xferIcon = findViewById(R.id.yourTrainXferIcon);
|
||||
departureCountdown = (CountdownTextView) findViewById(R.id.yourTrainDepartureCountdown);
|
||||
arrivalCountdown = (CountdownTextView) findViewById(R.id.yourTrainArrivalCountdown);
|
||||
alarmText = (TextView) findViewById(R.id.alarmText);
|
||||
}
|
||||
|
||||
private boolean mChecked;
|
||||
@ -75,13 +85,8 @@ public class YourTrainLayout extends RelativeLayout implements Checkable {
|
||||
}
|
||||
|
||||
private void setBackground() {
|
||||
if (isChecked()) {
|
||||
setBackgroundDrawable(getContext().getResources().getDrawable(
|
||||
R.color.blue_selection));
|
||||
} else {
|
||||
setBackgroundDrawable(getContext().getResources().getDrawable(
|
||||
R.color.gray));
|
||||
}
|
||||
int colorRes = isChecked() ? R.color.blue_selection : R.color.gray;
|
||||
setBackgroundResource(colorRes);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -89,11 +94,10 @@ public class YourTrainLayout extends RelativeLayout implements Checkable {
|
||||
setChecked(!isChecked());
|
||||
}
|
||||
|
||||
public void updateFromBoardedDeparture() {
|
||||
final Departure boardedDeparture = ((BartRunnerApplication) ((Activity) getContext())
|
||||
.getApplication()).getBoardedDeparture();
|
||||
if (boardedDeparture == null)
|
||||
public void updateFromBoardedDeparture(final Departure boardedDeparture) {
|
||||
if (boardedDeparture == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!boardedDeparture.equals(mDeparture)) {
|
||||
if (mDeparture != null) {
|
||||
@ -110,36 +114,23 @@ public class YourTrainLayout extends RelativeLayout implements Checkable {
|
||||
|
||||
mDeparture = boardedDeparture;
|
||||
|
||||
((TextView) findViewById(R.id.yourTrainDestinationText))
|
||||
.setText(boardedDeparture.getTrainDestination().toString());
|
||||
destinationText.setText(boardedDeparture.getTrainDestination().toString());
|
||||
trainLength.setText(boardedDeparture.getTrainLengthAndPlatform());
|
||||
|
||||
((TextView) findViewById(R.id.yourTrainTrainLengthText))
|
||||
.setText(boardedDeparture.getTrainLengthAndPlatform());
|
||||
|
||||
ImageView colorBar = (ImageView) findViewById(R.id.yourTrainDestinationColorBar);
|
||||
((GradientDrawable) colorBar.getDrawable()).setColor(Color
|
||||
.parseColor(boardedDeparture.getTrainDestinationColor()));
|
||||
ImageView bikeIcon = (ImageView) findViewById(R.id.yourTrainBikeIcon);
|
||||
colorBar.setBackgroundColor(boardedDeparture.getTrainDestinationColor());
|
||||
if (boardedDeparture.isBikeAllowed()) {
|
||||
bikeIcon.setImageDrawable(getResources().getDrawable(
|
||||
R.drawable.bike));
|
||||
bikeIcon.setImageResource(R.drawable.bike);
|
||||
} else {
|
||||
bikeIcon.setImageDrawable(getResources().getDrawable(
|
||||
R.drawable.nobike));
|
||||
bikeIcon.setImageResource(R.drawable.nobike);
|
||||
}
|
||||
if (boardedDeparture.getRequiresTransfer()) {
|
||||
findViewById(R.id.yourTrainXferIcon)
|
||||
.setVisibility(View.VISIBLE);
|
||||
xferIcon.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
findViewById(R.id.yourTrainXferIcon)
|
||||
.setVisibility(View.INVISIBLE);
|
||||
xferIcon.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
updateAlarmIndicator();
|
||||
|
||||
CountdownTextView departureCountdown = (CountdownTextView) findViewById(R.id.yourTrainDepartureCountdown);
|
||||
CountdownTextView arrivalCountdown = (CountdownTextView) findViewById(R.id.yourTrainArrivalCountdown);
|
||||
|
||||
final TextProvider textProvider = new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
@ -169,11 +160,10 @@ public class YourTrainLayout extends RelativeLayout implements Checkable {
|
||||
|
||||
private void updateAlarmIndicator() {
|
||||
if (!mDeparture.isAlarmPending()) {
|
||||
findViewById(R.id.alarmText).setVisibility(GONE);
|
||||
alarmText.setVisibility(GONE);
|
||||
} else {
|
||||
findViewById(R.id.alarmText).setVisibility(VISIBLE);
|
||||
((TextView) findViewById(R.id.alarmText)).setText(String
|
||||
.valueOf(mDeparture.getAlarmLeadTimeMinutes()));
|
||||
alarmText.setVisibility(VISIBLE);
|
||||
alarmText.setText(String.valueOf(mDeparture.getAlarmLeadTimeMinutes()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,8 @@
|
||||
package com.dougkeen.bart.data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@ -21,65 +16,36 @@ import android.widget.ViewSwitcher.ViewFactory;
|
||||
|
||||
import com.dougkeen.bart.R;
|
||||
import com.dougkeen.bart.controls.CountdownTextView;
|
||||
import com.dougkeen.bart.controls.DepartureListItemLayout;
|
||||
import com.dougkeen.bart.controls.CheckableLinearLayout;
|
||||
import com.dougkeen.bart.controls.TimedTextSwitcher;
|
||||
import com.dougkeen.bart.model.Departure;
|
||||
import com.dougkeen.bart.model.TextProvider;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
|
||||
|
||||
private Drawable noBikeDrawable;
|
||||
private Drawable bikeDrawable;
|
||||
|
||||
public DepartureArrayAdapter(Context context, int textViewResourceId,
|
||||
Departure[] objects) {
|
||||
super(context, textViewResourceId, objects);
|
||||
assignBikeDrawables();
|
||||
}
|
||||
|
||||
private void assignBikeDrawables() {
|
||||
noBikeDrawable = getContext().getResources().getDrawable(
|
||||
R.drawable.nobike);
|
||||
bikeDrawable = getContext().getResources().getDrawable(R.drawable.bike);
|
||||
}
|
||||
|
||||
public DepartureArrayAdapter(Context context, int resource,
|
||||
int textViewResourceId, Departure[] objects) {
|
||||
super(context, resource, textViewResourceId, objects);
|
||||
assignBikeDrawables();
|
||||
}
|
||||
|
||||
public DepartureArrayAdapter(Context context, int resource,
|
||||
int textViewResourceId, List<Departure> objects) {
|
||||
super(context, resource, textViewResourceId, objects);
|
||||
assignBikeDrawables();
|
||||
}
|
||||
|
||||
public DepartureArrayAdapter(Context context, int resource,
|
||||
int textViewResourceId) {
|
||||
super(context, resource, textViewResourceId);
|
||||
assignBikeDrawables();
|
||||
}
|
||||
|
||||
public DepartureArrayAdapter(Context context, int textViewResourceId,
|
||||
List<Departure> objects) {
|
||||
super(context, textViewResourceId, objects);
|
||||
assignBikeDrawables();
|
||||
}
|
||||
|
||||
public DepartureArrayAdapter(Context context, int textViewResourceId) {
|
||||
super(context, textViewResourceId);
|
||||
assignBikeDrawables();
|
||||
@SuppressWarnings("deprecation")
|
||||
public DepartureArrayAdapter(Context context) {
|
||||
super(context, 0 /* resource, unused since we override getView */);
|
||||
Resources resources = context.getResources();
|
||||
// We need to use the deprecated getDrawable since the newer version that
|
||||
// replaces it was only made available in API 21.
|
||||
noBikeDrawable = resources.getDrawable(R.drawable.nobike);
|
||||
bikeDrawable = resources.getDrawable(R.drawable.bike);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View view;
|
||||
if (convertView != null
|
||||
&& convertView instanceof DepartureListItemLayout) {
|
||||
if (convertView != null && convertView instanceof CheckableLinearLayout) {
|
||||
view = convertView;
|
||||
} else {
|
||||
view = new DepartureListItemLayout(getContext());
|
||||
view = LayoutInflater.from(getContext()).inflate(
|
||||
R.layout.departure_listing, parent, false /* attachToRoot */);
|
||||
}
|
||||
|
||||
final Departure departure = getItem(position);
|
||||
@ -132,10 +98,8 @@ public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
|
||||
});
|
||||
}
|
||||
|
||||
ImageView colorBar = (ImageView) view
|
||||
.findViewById(R.id.destinationColorBar);
|
||||
((GradientDrawable) colorBar.getDrawable()).setColor(Color
|
||||
.parseColor(departure.getTrainDestinationColor()));
|
||||
view.findViewById(R.id.destinationColorBar)
|
||||
.setBackgroundColor(departure.getTrainDestinationColor());
|
||||
CountdownTextView countdownTextView = (CountdownTextView) view
|
||||
.findViewById(R.id.countdown);
|
||||
countdownTextView.setText(departure.getCountdownText());
|
||||
@ -171,7 +135,7 @@ public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
ImageView bikeIcon = (ImageView) view.findViewById(R.id.bikeIcon);
|
||||
if (departure.isBikeAllowed()) {
|
||||
bikeIcon.setImageDrawable(bikeDrawable);
|
||||
@ -179,11 +143,9 @@ public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
|
||||
bikeIcon.setImageDrawable(noBikeDrawable);
|
||||
}
|
||||
if (departure.getRequiresTransfer()) {
|
||||
view.findViewById(R.id.xferIcon)
|
||||
.setVisibility(View.VISIBLE);
|
||||
view.findViewById(R.id.xferIcon).setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
view.findViewById(R.id.xferIcon)
|
||||
.setVisibility(View.INVISIBLE);
|
||||
view.findViewById(R.id.xferIcon).setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
return view;
|
||||
|
@ -1,18 +1,14 @@
|
||||
package com.dougkeen.bart.model;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.ColorInt;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.app.NotificationCompat.Builder;
|
||||
import android.util.Log;
|
||||
@ -23,6 +19,12 @@ import com.dougkeen.bart.activities.ViewDeparturesActivity;
|
||||
import com.dougkeen.bart.services.BoardedDepartureService;
|
||||
import com.dougkeen.util.Observable;
|
||||
|
||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
public class Departure implements Parcelable, Comparable<Departure> {
|
||||
private static final int MINIMUM_MERGE_OVERLAP_MILLIS = 5000;
|
||||
private static final int EXPIRE_MINUTES_AFTER_ARRIVAL = 1;
|
||||
@ -133,8 +135,9 @@ public class Departure implements Parcelable, Comparable<Departure> {
|
||||
this.line = line;
|
||||
}
|
||||
|
||||
public String getTrainDestinationColor() {
|
||||
return destinationColor;
|
||||
@ColorInt
|
||||
public int getTrainDestinationColor() {
|
||||
return Color.parseColor(destinationColor);
|
||||
}
|
||||
|
||||
public void setTrainDestinationColor(String destinationColor) {
|
||||
@ -627,33 +630,36 @@ public class Departure implements Parcelable, Comparable<Departure> {
|
||||
final Intent cancelAlarmIntent = new Intent(context,
|
||||
BoardedDepartureService.class);
|
||||
cancelAlarmIntent.putExtra("cancelNotifications", true);
|
||||
String title = getOrigin().shortName + " to " + getPassengerDestination().shortName;
|
||||
|
||||
Builder notificationBuilder = new NotificationCompat.Builder(context)
|
||||
.setOngoing(true)
|
||||
.setSmallIcon(R.drawable.ic_stat_notification)
|
||||
.setContentTitle(
|
||||
getOrigin().shortName + " to "
|
||||
+ getPassengerDestination().shortName)
|
||||
.setContentTitle(title)
|
||||
.setContentIntent(getNotificationIntent(context)).setWhen(0);
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= 16) {
|
||||
notificationBuilder.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
notificationBuilder
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
.setContentText(minutesText + " until departure");
|
||||
|
||||
if (isAlarmPending()) {
|
||||
notificationBuilder.addAction(
|
||||
R.drawable.ic_action_cancel_alarm,
|
||||
"Cancel alarm",
|
||||
PendingIntent.getService(context, 0, cancelAlarmIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT)).setSubText(
|
||||
"Alarm " + getAlarmLeadTimeMinutes()
|
||||
+ " minutes before departure");
|
||||
PendingIntent pendingIntent = PendingIntent.getService(
|
||||
context, 0, cancelAlarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
String subText = "Alarm " + getAlarmLeadTimeMinutes() + " minutes before departure";
|
||||
|
||||
notificationBuilder
|
||||
.addAction(R.drawable.ic_action_cancel_alarm, "Cancel alarm", pendingIntent)
|
||||
.setSubText(subText);
|
||||
}
|
||||
} else if (isAlarmPending()) {
|
||||
notificationBuilder.setContentText(minutesText
|
||||
String text = minutesText
|
||||
+ " to departure (alarm at " + getAlarmLeadTimeMinutes()
|
||||
+ " min" + ((getAlarmLeadTimeMinutes() == 1) ? "" : "s")
|
||||
+ ")");
|
||||
+ ")";
|
||||
notificationBuilder.setContentText(text);
|
||||
} else {
|
||||
notificationBuilder
|
||||
.setContentText(minutesText + " until departure");
|
||||
notificationBuilder.setContentText(minutesText + " until departure");
|
||||
}
|
||||
|
||||
return notificationBuilder.build();
|
||||
|
@ -4,7 +4,6 @@ import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.Service;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@ -15,6 +14,7 @@ import android.os.HandlerThread;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.support.v4.app.NotificationManagerCompat;
|
||||
|
||||
import com.dougkeen.bart.BartRunnerApplication;
|
||||
import com.dougkeen.bart.model.Departure;
|
||||
@ -34,7 +34,7 @@ public class BoardedDepartureService extends Service implements
|
||||
private boolean mBound = false;
|
||||
private EtdService mEtdService;
|
||||
private StationPair mStationPair;
|
||||
private NotificationManager mNotificationManager;
|
||||
private NotificationManagerCompat mNotificationManager;
|
||||
private AlarmManager mAlarmManager;
|
||||
private Handler mHandler;
|
||||
private boolean mHasShutDown = false;
|
||||
@ -91,7 +91,7 @@ public class BoardedDepartureService extends Service implements
|
||||
|
||||
bindService(EtdService_.intent(this).get(), mConnection,
|
||||
Context.BIND_AUTO_CREATE);
|
||||
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
mNotificationManager = NotificationManagerCompat.from(this);
|
||||
mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
|
||||
mHandler = new Handler();
|
||||
super.onCreate();
|
||||
@ -302,8 +302,7 @@ public class BoardedDepartureService extends Service implements
|
||||
.getBoardedDeparture();
|
||||
if (boardedDeparture != null) {
|
||||
mNotificationManager.notify(DEPARTURE_NOTIFICATION_ID,
|
||||
boardedDeparture
|
||||
.createNotification(getApplicationContext()));
|
||||
boardedDeparture.createNotification(getApplicationContext()));
|
||||
}
|
||||
}
|
||||
|
||||
|
13
app/src/main/java/com/dougkeen/util/Assert.java
Normal file
13
app/src/main/java/com/dougkeen/util/Assert.java
Normal file
@ -0,0 +1,13 @@
|
||||
package com.dougkeen.util;
|
||||
|
||||
public final class Assert {
|
||||
// Uninstantiable
|
||||
private Assert() {}
|
||||
|
||||
public static <T> T notNull(T obj) {
|
||||
if (obj == null) {
|
||||
throw new AssertionError("Expected object to be non-null");
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
}
|
@ -1,77 +1,111 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge
|
||||
<com.dougkeen.bart.controls.CheckableLinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:bart="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
android:layout_height="fill_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
|
||||
<ImageView
|
||||
<!-- This layout is used when the height is >= 480 dp, eg usually in portrait mode. -->
|
||||
|
||||
<View
|
||||
android:id="@+id/destinationColorBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="64dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:src="@drawable/basic_rectangle" />
|
||||
tools:background="#F00"
|
||||
/>
|
||||
|
||||
<!-- Holds the destination, the train info, and the arrival time -->
|
||||
<LinearLayout
|
||||
android:id="@+id/topRow"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_toRightOf="@id/destinationColorBar">
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/destinationText"
|
||||
style="@style/DepartureDestinationText"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="marquee"
|
||||
android:singleLine="true" />
|
||||
android:singleLine="true"
|
||||
tools:text="Richmond"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/trainLengthText"
|
||||
style="@style/DepartureUncertaintyText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="9 cars, platform 2"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/estimatedArrival"
|
||||
style="@style/DepartureUncertaintyText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="Arrives ~11:12 AM (20 mins)"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Holds the bike and xfer icons -->
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bikeIcon"
|
||||
style="@style/BikeIcon" />
|
||||
style="@style/TrainInfoIcon"
|
||||
tools:src="@drawable/bike"
|
||||
/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/xferIcon"
|
||||
style="@style/TrainInfoIcon"
|
||||
android:src="@drawable/xfer"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Holds the departure countdown, uncertainty, and departure time -->
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:gravity="right"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<com.dougkeen.bart.controls.CountdownTextView
|
||||
android:id="@+id/countdown"
|
||||
style="@style/DepartureCountdownText"
|
||||
android:gravity="right"
|
||||
android:width="90dp"
|
||||
bart:tickInterval="1" />
|
||||
android:gravity="right"
|
||||
bart:tickInterval="1"
|
||||
tools:text="9m, 57s"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/uncertainty"
|
||||
style="@style/DepartureUncertaintyText"
|
||||
tools:text="(+8s)"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/departureTime"
|
||||
style="@style/DepartureUncertaintyText"
|
||||
tools:text="11:20 AM"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/xferIcon"
|
||||
style="@style/XferIcon"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@id/topRow"
|
||||
android:src="@drawable/xfer" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/trainLengthText"
|
||||
style="@style/DepartureUncertaintyText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/topRow"
|
||||
android:layout_toRightOf="@id/destinationColorBar" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/uncertainty"
|
||||
style="@style/DepartureUncertaintyText"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@id/topRow" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/estimatedArrival"
|
||||
style="@style/DepartureUncertaintyText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/trainLengthText"
|
||||
android:layout_toRightOf="@id/destinationColorBar" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/departureTime"
|
||||
style="@style/DepartureUncertaintyText"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@id/uncertainty" />
|
||||
|
||||
</merge>
|
||||
</com.dougkeen.bart.controls.CheckableLinearLayout>
|
||||
|
@ -1,64 +1,98 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge
|
||||
<com.dougkeen.bart.controls.CheckableLinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:bart="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
android:layout_height="fill_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
|
||||
<ImageView
|
||||
<!-- This layout is used when the height is less than 480 dp (eg usually in landscape mode) -->
|
||||
|
||||
<View
|
||||
android:id="@+id/destinationColorBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="45dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:src="@drawable/basic_rectangle" />
|
||||
tools:background="#F00"
|
||||
/>
|
||||
|
||||
<!-- Holds destination and train info/arrival -->
|
||||
<LinearLayout
|
||||
android:id="@+id/topRow"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_toRightOf="@id/destinationColorBar">
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/destinationText"
|
||||
style="@style/DepartureDestinationText"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="marquee"
|
||||
android:singleLine="true" />
|
||||
android:singleLine="true"
|
||||
tools:text="Richmond"
|
||||
/>
|
||||
|
||||
<com.dougkeen.bart.controls.TimedTextSwitcher
|
||||
android:id="@+id/trainLengthText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
bart:tickInterval="1"
|
||||
tools:text="9 cars, platform 2"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Holds bike and xfer icons -->
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bikeIcon"
|
||||
style="@style/BikeIcon" />
|
||||
style="@style/TrainInfoIcon"
|
||||
tools:src="@drawable/bike"
|
||||
/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/xferIcon"
|
||||
style="@style/TrainInfoIcon"
|
||||
android:src="@drawable/xfer"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Holds departure countdown and uncertainty/departure time-->
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:gravity="right"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<com.dougkeen.bart.controls.CountdownTextView
|
||||
android:id="@+id/countdown"
|
||||
style="@style/DepartureCountdownText"
|
||||
android:gravity="right"
|
||||
android:width="90dp"
|
||||
bart:tickInterval="1" />
|
||||
android:gravity="right"
|
||||
bart:tickInterval="1"
|
||||
tools:text="9m, 57s"
|
||||
/>
|
||||
|
||||
<com.dougkeen.bart.controls.TimedTextSwitcher
|
||||
android:id="@+id/uncertainty"
|
||||
style="@style/DepartureUncertaintyText"
|
||||
bart:tickInterval="1"
|
||||
tools:text="(+8s)"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/xferIcon"
|
||||
style="@style/XferIcon"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@id/topRow"
|
||||
android:src="@drawable/xfer" />
|
||||
|
||||
<com.dougkeen.bart.controls.TimedTextSwitcher
|
||||
android:id="@+id/trainLengthText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/topRow"
|
||||
android:layout_toRightOf="@id/destinationColorBar"
|
||||
bart:tickInterval="1" />
|
||||
|
||||
<com.dougkeen.bart.controls.TimedTextSwitcher
|
||||
android:id="@+id/uncertainty"
|
||||
style="@style/DepartureUncertaintyText"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@id/topRow"
|
||||
bart:tickInterval="1" />
|
||||
|
||||
</merge>
|
||||
</com.dougkeen.bart.controls.CheckableLinearLayout>
|
||||
|
@ -1,82 +1,121 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:bart="http://schemas.android.com/apk/res-auto" >
|
||||
xmlns:bart="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/alarmText"
|
||||
<!-- Holds the "Your Train" title and the alarm indicator -->
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/yourTrainHeader"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:text="@string/your_train"
|
||||
android:textAllCaps="true"
|
||||
android:textSize="20dp"
|
||||
android:textStyle="bold"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/alarmText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="right"
|
||||
android:drawableLeft="@drawable/ic_action_alarm"
|
||||
android:gravity="center_vertical"
|
||||
android:textSize="16dp"
|
||||
android:visibility="gone"
|
||||
tools:text="5"
|
||||
/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<!-- Holds the color bar, destination text, train info, bike icon, and xfer icon -->
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:drawableLeft="@drawable/ic_action_alarm"
|
||||
android:gravity="center_vertical"
|
||||
android:textSize="16dp"
|
||||
android:visibility="gone"></TextView>
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/yourTrainHeader"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:text="@string/your_train"
|
||||
android:textAllCaps="true"
|
||||
android:textSize="20dp"
|
||||
android:textStyle="bold" />
|
||||
<View
|
||||
android:id="@+id/yourTrainDestinationColorBar"
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="45dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
tools:background="#F00"
|
||||
/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/yourTrainDestinationColorBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="45dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_below="@id/yourTrainHeader"
|
||||
android:src="@drawable/basic_rectangle" />
|
||||
<!-- Holds the destination text and train info -->
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:orientation="vertical"
|
||||
android:padding="5dp"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/yourTrainDestinationText"
|
||||
style="@style/DepartureDestinationText"
|
||||
android:layout_below="@id/yourTrainHeader"
|
||||
android:layout_toRightOf="@id/yourTrainDestinationColorBar"
|
||||
android:ellipsize="marquee"
|
||||
android:singleLine="true" />
|
||||
<TextView
|
||||
android:id="@+id/yourTrainDestinationText"
|
||||
style="@style/DepartureDestinationText"
|
||||
android:ellipsize="marquee"
|
||||
android:singleLine="true"
|
||||
tools:text="Richmond"
|
||||
/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/yourTrainBikeIcon"
|
||||
style="@style/BikeIcon"
|
||||
android:layout_below="@id/yourTrainHeader"
|
||||
android:layout_toRightOf="@id/yourTrainDestinationText" />
|
||||
<TextView
|
||||
android:id="@+id/yourTrainTrainLengthText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="9 cars, platform 2"
|
||||
/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/yourTrainXferIcon"
|
||||
style="@style/XferIcon"
|
||||
android:layout_below="@id/yourTrainBikeIcon"
|
||||
android:layout_toRightOf="@id/yourTrainDestinationText"
|
||||
android:src="@drawable/xfer" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/yourTrainTrainLengthText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/yourTrainDestinationText"
|
||||
android:layout_toRightOf="@id/yourTrainDestinationColorBar"
|
||||
android:paddingLeft="5dp" />
|
||||
<!-- Holds the bike icon and xfer icon -->
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/yourTrainBikeIcon"
|
||||
style="@style/TrainInfoIcon"
|
||||
tools:src="@drawable/bike"
|
||||
/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/yourTrainXferIcon"
|
||||
style="@style/TrainInfoIcon"
|
||||
android:src="@drawable/xfer"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.dougkeen.bart.controls.CountdownTextView
|
||||
android:id="@+id/yourTrainDepartureCountdown"
|
||||
style="@style/DepartureCountdownText"
|
||||
android:layout_alignLeft="@id/yourTrainSection"
|
||||
android:layout_alignRight="@id/yourTrainSection"
|
||||
android:layout_below="@id/yourTrainTrainLengthText"
|
||||
bart:tickInterval="1" />
|
||||
bart:tickInterval="1"
|
||||
tools:text="Leaves in 15 min, 20s (+8s)"
|
||||
/>
|
||||
|
||||
<com.dougkeen.bart.controls.CountdownTextView
|
||||
android:id="@+id/yourTrainArrivalCountdown"
|
||||
style="@style/DepartureCountdownText"
|
||||
android:layout_alignLeft="@id/yourTrainSection"
|
||||
android:layout_alignRight="@id/yourTrainSection"
|
||||
android:layout_below="@id/yourTrainDepartureCountdown"
|
||||
android:ellipsize="end"
|
||||
bart:tickInterval="5" />
|
||||
bart:tickInterval="5"
|
||||
tools:text="Arrives ~11:12 AM (20 mins)"
|
||||
/>
|
||||
|
||||
</merge>
|
||||
</LinearLayout>
|
||||
|
@ -92,18 +92,10 @@
|
||||
<item name="android:gravity">center</item>
|
||||
</style>
|
||||
|
||||
<style name="BikeIcon">
|
||||
<style name="TrainInfoIcon">
|
||||
<item name="android:layout_width">wrap_content</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:layout_marginTop">5dp</item>
|
||||
<item name="android:layout_marginLeft">5dp</item>
|
||||
</style>
|
||||
|
||||
<style name="XferIcon">
|
||||
<item name="android:layout_width">wrap_content</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:layout_marginRight">87dp</item>
|
||||
<item name="android:layout_marginBottom">5dp</item>
|
||||
<item name="android:layout_margin">5dp</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user