Reorganized code
Implemented countdowns on routes list screen Implemented offline storage of last boarded departure selection
This commit is contained in:
parent
fae89f4c45
commit
f12860d87e
2
.settings/org.eclipse.core.resources.prefs
Normal file
2
.settings/org.eclipse.core.resources.prefs
Normal file
@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=UTF-8
|
@ -18,7 +18,8 @@
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme" >
|
||||
<activity
|
||||
android:name="RoutesListActivity"
|
||||
android:name=".activities.RoutesListActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:label="@string/app_name" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
@ -43,7 +44,7 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="ViewDeparturesActivity"
|
||||
android:name=".activities.ViewDeparturesActivity"
|
||||
android:label="@string/departures" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
@ -55,7 +56,7 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="ViewMapActivity"
|
||||
android:name=".activities.ViewMapActivity"
|
||||
android:label="@string/system_map" >
|
||||
</activity>
|
||||
|
||||
@ -66,14 +67,14 @@
|
||||
android:label="BartRunner data provider" />
|
||||
|
||||
<service
|
||||
android:name=".NotificationService"
|
||||
android:name=".services.NotificationService"
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name=".EtdService"
|
||||
android:name=".services.EtdService"
|
||||
android:exported="false" />
|
||||
|
||||
<receiver
|
||||
android:name=".AlarmBroadcastReceiver"
|
||||
android:name=".receivers.AlarmBroadcastReceiver"
|
||||
android:exported="false" >
|
||||
<intent-filter>
|
||||
<action android:name="com.dougkeen.action.ALARM" />
|
||||
|
@ -1,23 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:bart="http://schemas.android.com/apk/res/com.dougkeen.bart"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingRight="5dp" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/fareText"
|
||||
style="@style/FareTextView"
|
||||
<com.dougkeen.bart.controls.CountdownTextView
|
||||
android:id="@+id/countdownText"
|
||||
style="@style/DepartureCountdownText"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:maxLines="3" />
|
||||
android:layout_alignParentTop="true"
|
||||
android:gravity="right"
|
||||
android:width="90dp"
|
||||
bart:tickInterval="1" />
|
||||
|
||||
<com.dougkeen.bart.controls.TimedTextSwitcher
|
||||
android:id="@+id/uncertainty"
|
||||
style="@style/DepartureUncertaintyText"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@id/countdownText"
|
||||
bart:tickInterval="1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/originText"
|
||||
style="@style/FavoriteListingTextView"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_toLeftOf="@id/fareText"
|
||||
android:layout_toLeftOf="@id/countdownText"
|
||||
android:text="Origin" />
|
||||
|
||||
<TextView
|
||||
@ -32,7 +42,7 @@
|
||||
android:id="@+id/destinationText"
|
||||
style="@style/FavoriteListingTextView"
|
||||
android:layout_below="@id/originText"
|
||||
android:layout_toLeftOf="@id/fareText"
|
||||
android:layout_toLeftOf="@id/countdownText"
|
||||
android:layout_toRightOf="@id/to"
|
||||
android:text="Destination" />
|
||||
|
||||
|
@ -17,6 +17,14 @@
|
||||
android:layout_weight="1"
|
||||
android:visibility="gone" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress"
|
||||
style="?android:attr/progressBarStyleLarge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical|center_horizontal"
|
||||
android:layout_weight="1000" />
|
||||
|
||||
<FrameLayout
|
||||
style="ButtonBar"
|
||||
android:layout_width="match_parent"
|
||||
|
3
res/layout/uncertainty_textview.xml
Normal file
3
res/layout/uncertainty_textview.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="@style/DepartureUncertaintyText" />
|
@ -4,6 +4,7 @@
|
||||
<string name="app_name">BART Runner</string>
|
||||
<string name="favorite_routes">Favorite routes</string>
|
||||
<string name="empty_favorites_list_message">No favorite routes have been added yet</string>
|
||||
<string name="loading_message">Loading, please wait...</string>
|
||||
<string name="add_route">Add a route</string>
|
||||
<string name="origin">Origin</string>
|
||||
<string name="destination">Destination</string>
|
||||
|
@ -1,12 +1,27 @@
|
||||
package com.dougkeen.bart;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
import android.app.Application;
|
||||
import android.media.MediaPlayer;
|
||||
import android.os.Parcel;
|
||||
import android.util.Log;
|
||||
|
||||
import com.dougkeen.bart.model.Constants;
|
||||
import com.dougkeen.bart.model.Departure;
|
||||
import com.dougkeen.util.Observable;
|
||||
|
||||
public class BartRunnerApplication extends Application {
|
||||
private static final int FIVE_MINUTES = 5 * 60 * 1000;
|
||||
|
||||
private static final String CACHE_FILE_NAME = "lastBoardedDeparture";
|
||||
|
||||
private Departure mBoardedDeparture;
|
||||
|
||||
private Observable<Boolean> mAlarmPending = new Observable<Boolean>(false);
|
||||
@ -26,11 +41,73 @@ public class BartRunnerApplication extends Application {
|
||||
}
|
||||
|
||||
public Departure getBoardedDeparture() {
|
||||
if (mBoardedDeparture == null) {
|
||||
// see if there's a saved one
|
||||
File cachedDepartureFile = new File(getCacheDir(), CACHE_FILE_NAME);
|
||||
if (cachedDepartureFile.exists()) {
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = new FileInputStream(cachedDepartureFile);
|
||||
byte[] byteArray = IOUtils.toByteArray(inputStream);
|
||||
Parcel parcel = Parcel.obtain();
|
||||
parcel.unmarshall(byteArray, 0, byteArray.length);
|
||||
parcel.setDataPosition(0);
|
||||
Departure lastBoardedDeparture = Departure.CREATOR
|
||||
.createFromParcel(parcel);
|
||||
|
||||
/*
|
||||
* Check if the cached one is relatively recent. If so,
|
||||
* restore that to the application context
|
||||
*/
|
||||
long now = System.currentTimeMillis();
|
||||
if (lastBoardedDeparture.getEstimatedArrivalTime() >= now
|
||||
- FIVE_MINUTES
|
||||
|| lastBoardedDeparture.getMeanEstimate() >= now
|
||||
- 2 * FIVE_MINUTES) {
|
||||
mBoardedDeparture = lastBoardedDeparture;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.w(Constants.TAG,
|
||||
"Couldn't read or unmarshal lastBoardedDeparture file",
|
||||
e);
|
||||
try {
|
||||
cachedDepartureFile.delete();
|
||||
} catch (SecurityException anotherException) {
|
||||
Log.w(Constants.TAG,
|
||||
"Couldn't delete lastBoardedDeparture file",
|
||||
anotherException);
|
||||
}
|
||||
} finally {
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
return mBoardedDeparture;
|
||||
}
|
||||
|
||||
public void setBoardedDeparture(Departure boardedDeparture) {
|
||||
this.mBoardedDeparture = boardedDeparture;
|
||||
if (!ObjectUtils.equals(boardedDeparture, mBoardedDeparture)
|
||||
|| ObjectUtils.compare(mBoardedDeparture, boardedDeparture) != 0) {
|
||||
this.mBoardedDeparture = boardedDeparture;
|
||||
|
||||
if (mBoardedDeparture != null) {
|
||||
File cachedDepartureFile = new File(getCacheDir(),
|
||||
CACHE_FILE_NAME);
|
||||
FileOutputStream fileOutputStream = null;
|
||||
try {
|
||||
fileOutputStream = new FileOutputStream(cachedDepartureFile);
|
||||
Parcel parcel = Parcel.obtain();
|
||||
mBoardedDeparture.writeToParcel(parcel, 0);
|
||||
fileOutputStream.write(parcel.marshall());
|
||||
} catch (Exception e) {
|
||||
Log.w(Constants.TAG,
|
||||
"Couldn't write last boarded departure cache file",
|
||||
e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(fileOutputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAlarmSounding() {
|
||||
|
@ -1,131 +1,132 @@
|
||||
package com.dougkeen.bart;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.WazaBe.HoloEverywhere.AlertDialog;
|
||||
import com.dougkeen.bart.model.Station;
|
||||
|
||||
public abstract class AbstractRouteSelectionFragment extends DialogFragment {
|
||||
|
||||
private static final String KEY_LAST_SELECTED_DESTINATION = "lastSelectedDestination";
|
||||
private static final String KEY_LAST_SELECTED_ORIGIN = "lastSelectedOrigin";
|
||||
protected String mTitle;
|
||||
|
||||
public AbstractRouteSelectionFragment(String title) {
|
||||
super();
|
||||
mTitle = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
SharedPreferences preferences = getActivity().getPreferences(
|
||||
Context.MODE_PRIVATE);
|
||||
|
||||
final int lastSelectedOriginPosition = preferences.getInt(
|
||||
KEY_LAST_SELECTED_ORIGIN, 0);
|
||||
final int lastSelectedDestinationPosition = preferences.getInt(
|
||||
KEY_LAST_SELECTED_DESTINATION, 1);
|
||||
|
||||
final Dialog dialog = getDialog();
|
||||
final FragmentActivity activity = getActivity();
|
||||
ArrayAdapter<Station> originSpinnerAdapter = new ArrayAdapter<Station>(
|
||||
activity, android.R.layout.simple_spinner_item,
|
||||
Station.getStationList());
|
||||
originSpinnerAdapter
|
||||
.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
|
||||
final Spinner originSpinner = (Spinner) dialog
|
||||
.findViewById(R.id.origin_spinner);
|
||||
originSpinner.setAdapter(originSpinnerAdapter);
|
||||
originSpinner.setSelection(lastSelectedOriginPosition);
|
||||
|
||||
ArrayAdapter<Station> destinationSpinnerAdapter = new ArrayAdapter<Station>(
|
||||
activity, android.R.layout.simple_spinner_item,
|
||||
Station.getStationList());
|
||||
destinationSpinnerAdapter
|
||||
.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
|
||||
|
||||
final Spinner destinationSpinner = (Spinner) dialog
|
||||
.findViewById(R.id.destination_spinner);
|
||||
destinationSpinner.setAdapter(destinationSpinnerAdapter);
|
||||
destinationSpinner.setSelection(lastSelectedDestinationPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final FragmentActivity activity = getActivity();
|
||||
|
||||
return new AlertDialog.Builder(activity)
|
||||
.setTitle(mTitle)
|
||||
.setCancelable(true)
|
||||
.setView(R.layout.route_form)
|
||||
.setPositiveButton(R.string.ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
handleOkClick();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog,
|
||||
int whichButton) {
|
||||
dialog.cancel();
|
||||
}
|
||||
}).create();
|
||||
}
|
||||
|
||||
protected void handleOkClick() {
|
||||
final Dialog dialog = getDialog();
|
||||
final Spinner originSpinner = (Spinner) dialog
|
||||
.findViewById(R.id.origin_spinner);
|
||||
final Spinner destinationSpinner = (Spinner) dialog
|
||||
.findViewById(R.id.destination_spinner);
|
||||
|
||||
Station origin = (Station) originSpinner.getSelectedItem();
|
||||
Station destination = (Station) destinationSpinner.getSelectedItem();
|
||||
if (origin == null) {
|
||||
Toast.makeText(dialog.getContext(),
|
||||
com.dougkeen.bart.R.string.error_null_origin,
|
||||
Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
if (destination == null) {
|
||||
Toast.makeText(dialog.getContext(),
|
||||
com.dougkeen.bart.R.string.error_null_destination,
|
||||
Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
if (origin.equals(destination)) {
|
||||
Toast.makeText(
|
||||
dialog.getContext(),
|
||||
com.dougkeen.bart.R.string.error_matching_origin_and_destination,
|
||||
Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
final Editor prefsEditor = getActivity().getPreferences(
|
||||
Context.MODE_PRIVATE).edit();
|
||||
prefsEditor.putInt(KEY_LAST_SELECTED_ORIGIN,
|
||||
originSpinner.getSelectedItemPosition());
|
||||
prefsEditor.putInt(KEY_LAST_SELECTED_DESTINATION,
|
||||
destinationSpinner.getSelectedItemPosition());
|
||||
prefsEditor.commit();
|
||||
|
||||
onOkButtonClick(origin, destination);
|
||||
}
|
||||
|
||||
abstract protected void onOkButtonClick(Station origin, Station destination);
|
||||
package com.dougkeen.bart.activities;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.WazaBe.HoloEverywhere.AlertDialog;
|
||||
import com.dougkeen.bart.R;
|
||||
import com.dougkeen.bart.model.Station;
|
||||
|
||||
public abstract class AbstractRouteSelectionFragment extends DialogFragment {
|
||||
|
||||
private static final String KEY_LAST_SELECTED_DESTINATION = "lastSelectedDestination";
|
||||
private static final String KEY_LAST_SELECTED_ORIGIN = "lastSelectedOrigin";
|
||||
protected String mTitle;
|
||||
|
||||
public AbstractRouteSelectionFragment(String title) {
|
||||
super();
|
||||
mTitle = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
SharedPreferences preferences = getActivity().getPreferences(
|
||||
Context.MODE_PRIVATE);
|
||||
|
||||
final int lastSelectedOriginPosition = preferences.getInt(
|
||||
KEY_LAST_SELECTED_ORIGIN, 0);
|
||||
final int lastSelectedDestinationPosition = preferences.getInt(
|
||||
KEY_LAST_SELECTED_DESTINATION, 1);
|
||||
|
||||
final Dialog dialog = getDialog();
|
||||
final FragmentActivity activity = getActivity();
|
||||
ArrayAdapter<Station> originSpinnerAdapter = new ArrayAdapter<Station>(
|
||||
activity, android.R.layout.simple_spinner_item,
|
||||
Station.getStationList());
|
||||
originSpinnerAdapter
|
||||
.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
|
||||
final Spinner originSpinner = (Spinner) dialog
|
||||
.findViewById(R.id.origin_spinner);
|
||||
originSpinner.setAdapter(originSpinnerAdapter);
|
||||
originSpinner.setSelection(lastSelectedOriginPosition);
|
||||
|
||||
ArrayAdapter<Station> destinationSpinnerAdapter = new ArrayAdapter<Station>(
|
||||
activity, android.R.layout.simple_spinner_item,
|
||||
Station.getStationList());
|
||||
destinationSpinnerAdapter
|
||||
.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
|
||||
|
||||
final Spinner destinationSpinner = (Spinner) dialog
|
||||
.findViewById(R.id.destination_spinner);
|
||||
destinationSpinner.setAdapter(destinationSpinnerAdapter);
|
||||
destinationSpinner.setSelection(lastSelectedDestinationPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final FragmentActivity activity = getActivity();
|
||||
|
||||
return new AlertDialog.Builder(activity)
|
||||
.setTitle(mTitle)
|
||||
.setCancelable(true)
|
||||
.setView(R.layout.route_form)
|
||||
.setPositiveButton(R.string.ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
handleOkClick();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog,
|
||||
int whichButton) {
|
||||
dialog.cancel();
|
||||
}
|
||||
}).create();
|
||||
}
|
||||
|
||||
protected void handleOkClick() {
|
||||
final Dialog dialog = getDialog();
|
||||
final Spinner originSpinner = (Spinner) dialog
|
||||
.findViewById(R.id.origin_spinner);
|
||||
final Spinner destinationSpinner = (Spinner) dialog
|
||||
.findViewById(R.id.destination_spinner);
|
||||
|
||||
Station origin = (Station) originSpinner.getSelectedItem();
|
||||
Station destination = (Station) destinationSpinner.getSelectedItem();
|
||||
if (origin == null) {
|
||||
Toast.makeText(dialog.getContext(),
|
||||
com.dougkeen.bart.R.string.error_null_origin,
|
||||
Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
if (destination == null) {
|
||||
Toast.makeText(dialog.getContext(),
|
||||
com.dougkeen.bart.R.string.error_null_destination,
|
||||
Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
if (origin.equals(destination)) {
|
||||
Toast.makeText(
|
||||
dialog.getContext(),
|
||||
com.dougkeen.bart.R.string.error_matching_origin_and_destination,
|
||||
Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
final Editor prefsEditor = getActivity().getPreferences(
|
||||
Context.MODE_PRIVATE).edit();
|
||||
prefsEditor.putInt(KEY_LAST_SELECTED_ORIGIN,
|
||||
originSpinner.getSelectedItemPosition());
|
||||
prefsEditor.putInt(KEY_LAST_SELECTED_DESTINATION,
|
||||
destinationSpinner.getSelectedItemPosition());
|
||||
prefsEditor.commit();
|
||||
|
||||
onOkButtonClick(origin, destination);
|
||||
}
|
||||
|
||||
abstract protected void onOkButtonClick(Station origin, Station destination);
|
||||
}
|
@ -1,55 +1,56 @@
|
||||
package com.dougkeen.bart;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
|
||||
import com.dougkeen.bart.data.RoutesColumns;
|
||||
import com.dougkeen.bart.model.Constants;
|
||||
import com.dougkeen.bart.model.Station;
|
||||
|
||||
public class AddRouteDialogFragment extends AbstractRouteSelectionFragment {
|
||||
public AddRouteDialogFragment(String title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
final View checkboxText = getDialog().findViewById(
|
||||
R.id.return_checkbox_text);
|
||||
final View checkbox = getDialog().findViewById(R.id.return_checkbox);
|
||||
checkboxText.setVisibility(View.VISIBLE);
|
||||
checkbox.setVisibility(View.VISIBLE);
|
||||
checkboxText.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
checkbox.performClick();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onOkButtonClick(Station origin, Station destination) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(RoutesColumns.FROM_STATION.string, origin.abbreviation);
|
||||
values.put(RoutesColumns.TO_STATION.string, destination.abbreviation);
|
||||
|
||||
getActivity().getContentResolver().insert(
|
||||
Constants.FAVORITE_CONTENT_URI, values);
|
||||
|
||||
if (((CheckBox) getDialog().findViewById(R.id.return_checkbox))
|
||||
.isChecked()) {
|
||||
values = new ContentValues();
|
||||
values.put(RoutesColumns.FROM_STATION.string,
|
||||
destination.abbreviation);
|
||||
values.put(RoutesColumns.TO_STATION.string, origin.abbreviation);
|
||||
|
||||
getActivity().getContentResolver().insert(
|
||||
Constants.FAVORITE_CONTENT_URI, values);
|
||||
}
|
||||
|
||||
dismiss();
|
||||
}
|
||||
|
||||
}
|
||||
package com.dougkeen.bart.activities;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
|
||||
import com.dougkeen.bart.R;
|
||||
import com.dougkeen.bart.data.RoutesColumns;
|
||||
import com.dougkeen.bart.model.Constants;
|
||||
import com.dougkeen.bart.model.Station;
|
||||
|
||||
public class AddRouteDialogFragment extends AbstractRouteSelectionFragment {
|
||||
public AddRouteDialogFragment(String title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
final View checkboxText = getDialog().findViewById(
|
||||
R.id.return_checkbox_text);
|
||||
final View checkbox = getDialog().findViewById(R.id.return_checkbox);
|
||||
checkboxText.setVisibility(View.VISIBLE);
|
||||
checkbox.setVisibility(View.VISIBLE);
|
||||
checkboxText.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
checkbox.performClick();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onOkButtonClick(Station origin, Station destination) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(RoutesColumns.FROM_STATION.string, origin.abbreviation);
|
||||
values.put(RoutesColumns.TO_STATION.string, destination.abbreviation);
|
||||
|
||||
getActivity().getContentResolver().insert(
|
||||
Constants.FAVORITE_CONTENT_URI, values);
|
||||
|
||||
if (((CheckBox) getDialog().findViewById(R.id.return_checkbox))
|
||||
.isChecked()) {
|
||||
values = new ContentValues();
|
||||
values.put(RoutesColumns.FROM_STATION.string,
|
||||
destination.abbreviation);
|
||||
values.put(RoutesColumns.TO_STATION.string, origin.abbreviation);
|
||||
|
||||
getActivity().getContentResolver().insert(
|
||||
Constants.FAVORITE_CONTENT_URI, values);
|
||||
}
|
||||
|
||||
dismiss();
|
||||
}
|
||||
|
||||
}
|
@ -1,21 +1,21 @@
|
||||
package com.dougkeen.bart;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
import com.dougkeen.bart.model.Constants;
|
||||
import com.dougkeen.bart.model.Station;
|
||||
|
||||
public class QuickRouteDialogFragment extends AbstractRouteSelectionFragment {
|
||||
|
||||
public QuickRouteDialogFragment(String title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onOkButtonClick(Station origin, Station destination) {
|
||||
startActivity(new Intent(Intent.ACTION_VIEW,
|
||||
Constants.ARBITRARY_ROUTE_CONTENT_URI_ROOT.buildUpon()
|
||||
.appendPath(origin.abbreviation)
|
||||
.appendPath(destination.abbreviation).build()));
|
||||
}
|
||||
}
|
||||
package com.dougkeen.bart.activities;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
import com.dougkeen.bart.model.Constants;
|
||||
import com.dougkeen.bart.model.Station;
|
||||
|
||||
public class QuickRouteDialogFragment extends AbstractRouteSelectionFragment {
|
||||
|
||||
public QuickRouteDialogFragment(String title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onOkButtonClick(Station origin, Station destination) {
|
||||
startActivity(new Intent(Intent.ACTION_VIEW,
|
||||
Constants.ARBITRARY_ROUTE_CONTENT_URI_ROOT.buildUpon()
|
||||
.appendPath(origin.abbreviation)
|
||||
.appendPath(destination.abbreviation).build()));
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.dougkeen.bart;
|
||||
package com.dougkeen.bart.activities;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
@ -8,17 +8,16 @@ import android.content.ContentValues;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.database.CursorWrapper;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||
import android.support.v4.content.CursorLoader;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.Button;
|
||||
import android.widget.CursorAdapter;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.SimpleCursorAdapter;
|
||||
import android.widget.SimpleCursorAdapter.ViewBinder;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.WazaBe.HoloEverywhere.AlertDialog;
|
||||
@ -27,18 +26,23 @@ import com.actionbarsherlock.view.ActionMode;
|
||||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuInflater;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
import com.dougkeen.bart.R;
|
||||
import com.dougkeen.bart.controls.Ticker;
|
||||
import com.dougkeen.bart.data.CursorUtils;
|
||||
import com.dougkeen.bart.data.FavoritesArrayAdapter;
|
||||
import com.dougkeen.bart.data.RoutesColumns;
|
||||
import com.dougkeen.bart.model.Constants;
|
||||
import com.dougkeen.bart.model.Station;
|
||||
import com.dougkeen.bart.model.StationPair;
|
||||
import com.dougkeen.bart.networktasks.GetRouteFareTask;
|
||||
|
||||
public class RoutesListActivity extends SherlockFragmentActivity {
|
||||
public class RoutesListActivity extends SherlockFragmentActivity implements
|
||||
LoaderCallbacks<Cursor> {
|
||||
private static final int FAVORITES_LOADER_ID = 0;
|
||||
|
||||
private static final TimeZone PACIFIC_TIME = TimeZone
|
||||
.getTimeZone("America/Los_Angeles");
|
||||
|
||||
protected Cursor mQuery;
|
||||
|
||||
private Uri mCurrentlySelectedUri;
|
||||
|
||||
private Station mCurrentlySelectedOrigin;
|
||||
@ -46,6 +50,8 @@ public class RoutesListActivity extends SherlockFragmentActivity {
|
||||
|
||||
private ActionMode mActionMode;
|
||||
|
||||
private FavoritesArrayAdapter mRoutesAdapter;
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@ -53,51 +59,24 @@ public class RoutesListActivity extends SherlockFragmentActivity {
|
||||
setContentView(R.layout.main);
|
||||
setTitle(R.string.favorite_routes);
|
||||
|
||||
mQuery = managedQuery(Constants.FAVORITE_CONTENT_URI, new String[] {
|
||||
RoutesColumns._ID.string, RoutesColumns.FROM_STATION.string,
|
||||
RoutesColumns.TO_STATION.string, RoutesColumns.FARE.string,
|
||||
RoutesColumns.FARE_LAST_UPDATED.string,
|
||||
RoutesColumns.AVERAGE_TRIP_SAMPLE_COUNT.string,
|
||||
RoutesColumns.AVERAGE_TRIP_LENGTH.string }, null, null,
|
||||
RoutesColumns._ID.string);
|
||||
mRoutesAdapter = new FavoritesArrayAdapter(this,
|
||||
R.layout.favorite_listing);
|
||||
|
||||
refreshFares();
|
||||
getSupportLoaderManager().initLoader(FAVORITES_LOADER_ID, null, this);
|
||||
|
||||
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
|
||||
R.layout.favorite_listing, mQuery, new String[] {
|
||||
RoutesColumns.FROM_STATION.string,
|
||||
RoutesColumns.TO_STATION.string,
|
||||
RoutesColumns.FARE.string }, new int[] {
|
||||
R.id.originText, R.id.destinationText, R.id.fareText });
|
||||
adapter.setViewBinder(new ViewBinder() {
|
||||
public boolean setViewValue(View view, Cursor cursor,
|
||||
int columnIndex) {
|
||||
if (view.getId() == R.id.fareText) {
|
||||
String fare = cursor.getString(columnIndex);
|
||||
if (fare != null) {
|
||||
((TextView) view).setSingleLine(false);
|
||||
((TextView) view).setText("Fare:\n" + fare);
|
||||
}
|
||||
} else {
|
||||
((TextView) view).setText(Station.getByAbbreviation(cursor
|
||||
.getString(columnIndex)).name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
setListAdapter(adapter);
|
||||
setListAdapter(mRoutesAdapter);
|
||||
getListView().setOnItemClickListener(
|
||||
new AdapterView.OnItemClickListener() {
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> l, View v,
|
||||
int position, long id) {
|
||||
;
|
||||
startActivity(new Intent(Intent.ACTION_VIEW,
|
||||
ContentUris.withAppendedId(
|
||||
Constants.FAVORITE_CONTENT_URI, id)));
|
||||
Constants.FAVORITE_CONTENT_URI,
|
||||
getListAdapter().getItem(position)
|
||||
.getId())));
|
||||
}
|
||||
|
||||
});
|
||||
getListView().setEmptyView(findViewById(android.R.id.empty));
|
||||
getListView().setOnItemLongClickListener(
|
||||
@ -109,17 +88,13 @@ public class RoutesListActivity extends SherlockFragmentActivity {
|
||||
mActionMode.finish();
|
||||
}
|
||||
|
||||
mCurrentlySelectedUri = ContentUris.withAppendedId(
|
||||
Constants.FAVORITE_CONTENT_URI, id);
|
||||
StationPair item = getListAdapter().getItem(position);
|
||||
|
||||
CursorWrapper item = (CursorWrapper) getListAdapter()
|
||||
.getItem(position);
|
||||
Station orig = Station.getByAbbreviation(CursorUtils
|
||||
.getString(item, RoutesColumns.FROM_STATION));
|
||||
Station dest = Station.getByAbbreviation(CursorUtils
|
||||
.getString(item, RoutesColumns.TO_STATION));
|
||||
mCurrentlySelectedOrigin = orig;
|
||||
mCurrentlySelectedDestination = dest;
|
||||
mCurrentlySelectedUri = ContentUris.withAppendedId(
|
||||
Constants.FAVORITE_CONTENT_URI, item.getId());
|
||||
|
||||
mCurrentlySelectedOrigin = item.getOrigin();
|
||||
mCurrentlySelectedDestination = item.getDestination();
|
||||
|
||||
startContextualActionMode();
|
||||
return true;
|
||||
@ -157,31 +132,58 @@ public class RoutesListActivity extends SherlockFragmentActivity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||
return new CursorLoader(this, Constants.FAVORITE_CONTENT_URI,
|
||||
new String[] { RoutesColumns._ID.string,
|
||||
RoutesColumns.FROM_STATION.string,
|
||||
RoutesColumns.TO_STATION.string,
|
||||
RoutesColumns.FARE.string,
|
||||
RoutesColumns.FARE_LAST_UPDATED.string,
|
||||
RoutesColumns.AVERAGE_TRIP_SAMPLE_COUNT.string,
|
||||
RoutesColumns.AVERAGE_TRIP_LENGTH.string }, null, null,
|
||||
RoutesColumns._ID.string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
|
||||
if (cursor.getCount() == 0) {
|
||||
((TextView) findViewById(android.R.id.empty))
|
||||
.setText(R.string.empty_favorites_list_message);
|
||||
}
|
||||
mRoutesAdapter.updateFromCursor(cursor);
|
||||
refreshFares(cursor);
|
||||
findViewById(R.id.progress).setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<Cursor> loader) {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private AdapterView<ListAdapter> getListView() {
|
||||
return (AdapterView<ListAdapter>) findViewById(android.R.id.list);
|
||||
}
|
||||
|
||||
private CursorAdapter mListAdapter;
|
||||
|
||||
protected CursorAdapter getListAdapter() {
|
||||
return mListAdapter;
|
||||
protected FavoritesArrayAdapter getListAdapter() {
|
||||
return mRoutesAdapter;
|
||||
}
|
||||
|
||||
protected void setListAdapter(SimpleCursorAdapter adapter) {
|
||||
mListAdapter = adapter;
|
||||
getListView().setAdapter(mListAdapter);
|
||||
protected void setListAdapter(FavoritesArrayAdapter adapter) {
|
||||
mRoutesAdapter = adapter;
|
||||
getListView().setAdapter(mRoutesAdapter);
|
||||
}
|
||||
|
||||
private void refreshFares() {
|
||||
if (mQuery.moveToFirst()) {
|
||||
private void refreshFares(Cursor cursor) {
|
||||
if (cursor.moveToFirst()) {
|
||||
do {
|
||||
final Station orig = Station.getByAbbreviation(CursorUtils
|
||||
.getString(mQuery, RoutesColumns.FROM_STATION));
|
||||
.getString(cursor, RoutesColumns.FROM_STATION));
|
||||
final Station dest = Station.getByAbbreviation(CursorUtils
|
||||
.getString(mQuery, RoutesColumns.TO_STATION));
|
||||
final Long id = CursorUtils.getLong(mQuery, RoutesColumns._ID);
|
||||
final Long lastUpdateMillis = CursorUtils.getLong(mQuery,
|
||||
.getString(cursor, RoutesColumns.TO_STATION));
|
||||
final Long id = CursorUtils.getLong(cursor, RoutesColumns._ID);
|
||||
final Long lastUpdateMillis = CursorUtils.getLong(cursor,
|
||||
RoutesColumns.FARE_LAST_UPDATED);
|
||||
|
||||
Calendar now = Calendar.getInstance();
|
||||
@ -215,7 +217,7 @@ public class RoutesListActivity extends SherlockFragmentActivity {
|
||||
};
|
||||
fareTask.execute(new GetRouteFareTask.Params(orig, dest));
|
||||
}
|
||||
} while (mQuery.moveToNext());
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,9 +237,41 @@ public class RoutesListActivity extends SherlockFragmentActivity {
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
((TextView) findViewById(android.R.id.empty))
|
||||
.setText(R.string.empty_favorites_list_message);
|
||||
refreshFares();
|
||||
Ticker.getInstance().startTicking(this);
|
||||
if (mRoutesAdapter != null && !mRoutesAdapter.isEmpty()
|
||||
&& !mRoutesAdapter.areEtdListenersActive()) {
|
||||
mRoutesAdapter.setUpEtdListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
if (mRoutesAdapter != null && mRoutesAdapter.areEtdListenersActive()) {
|
||||
mRoutesAdapter.clearEtdListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
Ticker.getInstance().stopTicking(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mRoutesAdapter != null) {
|
||||
mRoutesAdapter.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
if (hasFocus) {
|
||||
Ticker.getInstance().startTicking(this);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
@ -1,4 +1,4 @@
|
||||
package com.dougkeen.bart;
|
||||
package com.dougkeen.bart.activities;
|
||||
|
||||
import net.simonvt.widget.NumberPicker;
|
||||
import android.app.Dialog;
|
||||
@ -12,6 +12,9 @@ import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
|
||||
import com.WazaBe.HoloEverywhere.AlertDialog;
|
||||
import com.dougkeen.bart.BartRunnerApplication;
|
||||
import com.dougkeen.bart.R;
|
||||
import com.dougkeen.bart.services.NotificationService;
|
||||
|
||||
public class TrainAlertDialogFragment extends DialogFragment {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,45 +1,46 @@
|
||||
package com.dougkeen.bart;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import com.actionbarsherlock.app.SherlockActivity;
|
||||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuInflater;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
|
||||
public class ViewMapActivity extends SherlockActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
WebView webview = new WebView(this);
|
||||
setContentView(webview);
|
||||
|
||||
webview.getSettings().setBuiltInZoomControls(true);
|
||||
webview.getSettings().setSupportZoom(true);
|
||||
|
||||
webview.loadUrl("file:///android_res/drawable/map.png");
|
||||
|
||||
getSupportActionBar().setHomeButtonEnabled(true);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getSupportMenuInflater();
|
||||
inflater.inflate(R.menu.system_map_menu, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
}
|
||||
package com.dougkeen.bart.activities;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import com.actionbarsherlock.app.SherlockActivity;
|
||||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuInflater;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
import com.dougkeen.bart.R;
|
||||
|
||||
public class ViewMapActivity extends SherlockActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
WebView webview = new WebView(this);
|
||||
setContentView(webview);
|
||||
|
||||
webview.getSettings().setBuiltInZoomControls(true);
|
||||
webview.getSettings().setSupportZoom(true);
|
||||
|
||||
webview.loadUrl("file:///android_res/drawable/map.png");
|
||||
|
||||
getSupportActionBar().setHomeButtonEnabled(true);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getSupportMenuInflater();
|
||||
inflater.inflate(R.menu.system_map_menu, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
}
|
@ -37,7 +37,7 @@ public class CountdownTextView extends TextView implements
|
||||
|
||||
public void setTextProvider(TextProvider provider) {
|
||||
mTextProvider = provider;
|
||||
Ticker.getInstance().addSubscriber(this);
|
||||
Ticker.getInstance().addSubscriber(this, getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3,6 +3,7 @@ package com.dougkeen.bart.controls;
|
||||
import java.util.Iterator;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
|
||||
public class Ticker {
|
||||
@ -16,6 +17,8 @@ public class Ticker {
|
||||
|
||||
private WeakHashMap<TickSubscriber, Object> mSubscribers;
|
||||
|
||||
private WeakHashMap<Context, Object> mTickerHosts;
|
||||
|
||||
private TickerEngine mEngine;
|
||||
|
||||
private static class TickerEngine implements Runnable {
|
||||
@ -84,26 +87,28 @@ public class Ticker {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public void addSubscriber(TickSubscriber subscriber) {
|
||||
public void addSubscriber(TickSubscriber subscriber, Context host) {
|
||||
if (!mSubscribers.containsKey(subscriber) && subscriber != null) {
|
||||
mSubscribers.put(subscriber, null);
|
||||
startTicking();
|
||||
startTicking(host);
|
||||
}
|
||||
}
|
||||
|
||||
private Ticker() {
|
||||
mSubscribers = new WeakHashMap<TickSubscriber, Object>();
|
||||
mTickerHosts = new WeakHashMap<Context, Object>();
|
||||
mEngine = new TickerEngine(this);
|
||||
}
|
||||
|
||||
public void startTicking() {
|
||||
public void startTicking(Context host) {
|
||||
mTickerHosts.put(host, true);
|
||||
if (!mEngine.isOn())
|
||||
mEngine.run();
|
||||
}
|
||||
|
||||
public void stopTicking() {
|
||||
if (mEngine.isOn())
|
||||
public void stopTicking(Context host) {
|
||||
mTickerHosts.remove(host);
|
||||
if (mEngine.isOn() && mTickerHosts.isEmpty())
|
||||
mEngine.stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ public class TimedTextSwitcher extends TextSwitcher implements
|
||||
|
||||
public void setTextProvider(TextProvider textProvider) {
|
||||
mTextProvider = textProvider;
|
||||
Ticker.getInstance().addSubscriber(this);
|
||||
Ticker.getInstance().addSubscriber(this, getContext());
|
||||
}
|
||||
|
||||
private CharSequence mLastText;
|
||||
|
@ -1,148 +1,149 @@
|
||||
package com.dougkeen.bart;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextSwitcher;
|
||||
import android.widget.TextView;
|
||||
import android.widget.ViewSwitcher.ViewFactory;
|
||||
|
||||
import com.dougkeen.bart.controls.CountdownTextView;
|
||||
import com.dougkeen.bart.controls.TimedTextSwitcher;
|
||||
import com.dougkeen.bart.model.Departure;
|
||||
import com.dougkeen.bart.model.TextProvider;
|
||||
|
||||
public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
|
||||
|
||||
public DepartureArrayAdapter(Context context, int textViewResourceId,
|
||||
Departure[] objects) {
|
||||
super(context, textViewResourceId, objects);
|
||||
}
|
||||
|
||||
public DepartureArrayAdapter(Context context, int resource,
|
||||
int textViewResourceId, Departure[] objects) {
|
||||
super(context, resource, textViewResourceId, objects);
|
||||
}
|
||||
|
||||
public DepartureArrayAdapter(Context context, int resource,
|
||||
int textViewResourceId, List<Departure> objects) {
|
||||
super(context, resource, textViewResourceId, objects);
|
||||
}
|
||||
|
||||
public DepartureArrayAdapter(Context context, int resource,
|
||||
int textViewResourceId) {
|
||||
super(context, resource, textViewResourceId);
|
||||
}
|
||||
|
||||
public DepartureArrayAdapter(Context context, int textViewResourceId,
|
||||
List<Departure> objects) {
|
||||
super(context, textViewResourceId, objects);
|
||||
}
|
||||
|
||||
public DepartureArrayAdapter(Context context, int textViewResourceId) {
|
||||
super(context, textViewResourceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View view;
|
||||
if (convertView != null && convertView instanceof RelativeLayout) {
|
||||
view = convertView;
|
||||
} else {
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
view = inflater.inflate(R.layout.departure_listing, parent, false);
|
||||
}
|
||||
|
||||
final Departure departure = getItem(position);
|
||||
((TextView) view.findViewById(R.id.destinationText)).setText(departure
|
||||
.getTrainDestination().toString());
|
||||
|
||||
TimedTextSwitcher textSwitcher = (TimedTextSwitcher) view
|
||||
.findViewById(R.id.trainLengthText);
|
||||
initTextSwitcher(textSwitcher);
|
||||
|
||||
final String estimatedArrivalTimeText = departure
|
||||
.getEstimatedArrivalTimeText(getContext());
|
||||
if (!StringUtils.isBlank(estimatedArrivalTimeText)) {
|
||||
textSwitcher.setCurrentText("Est. arrival "
|
||||
+ estimatedArrivalTimeText);
|
||||
} else {
|
||||
textSwitcher.setCurrentText(departure.getTrainLengthText());
|
||||
}
|
||||
textSwitcher.setTextProvider(new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
if (tickNumber % 4 == 0) {
|
||||
return departure.getTrainLengthText();
|
||||
} else {
|
||||
final String estimatedArrivalTimeText = departure
|
||||
.getEstimatedArrivalTimeText(getContext());
|
||||
if (StringUtils.isBlank(estimatedArrivalTimeText)) {
|
||||
return "";
|
||||
} else {
|
||||
return "Est. arrival " + estimatedArrivalTimeText;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ImageView colorBar = (ImageView) view
|
||||
.findViewById(R.id.destinationColorBar);
|
||||
((GradientDrawable) colorBar.getDrawable()).setColor(Color
|
||||
.parseColor(departure.getTrainDestinationColor()));
|
||||
CountdownTextView countdownTextView = (CountdownTextView) view
|
||||
.findViewById(R.id.countdown);
|
||||
countdownTextView.setText(departure.getCountdownText());
|
||||
countdownTextView.setTextProvider(new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
return departure.getCountdownText();
|
||||
}
|
||||
});
|
||||
((TextView) view.findViewById(R.id.uncertainty)).setText(departure
|
||||
.getUncertaintyText());
|
||||
if (departure.isBikeAllowed()) {
|
||||
((ImageView) view.findViewById(R.id.bikeIcon))
|
||||
.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
((ImageView) view.findViewById(R.id.bikeIcon))
|
||||
.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
if (departure.getRequiresTransfer()) {
|
||||
((ImageView) view.findViewById(R.id.xferIcon))
|
||||
.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
((ImageView) view.findViewById(R.id.xferIcon))
|
||||
.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private void initTextSwitcher(TextSwitcher textSwitcher) {
|
||||
if (textSwitcher.getInAnimation() == null) {
|
||||
textSwitcher.setFactory(new ViewFactory() {
|
||||
public View makeView() {
|
||||
return LayoutInflater.from(getContext()).inflate(
|
||||
R.layout.train_length_arrival_textview, null);
|
||||
}
|
||||
});
|
||||
|
||||
textSwitcher.setInAnimation(AnimationUtils.loadAnimation(
|
||||
getContext(), android.R.anim.slide_in_left));
|
||||
textSwitcher.setOutAnimation(AnimationUtils.loadAnimation(
|
||||
getContext(), android.R.anim.slide_out_right));
|
||||
}
|
||||
}
|
||||
}
|
||||
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.graphics.drawable.GradientDrawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextSwitcher;
|
||||
import android.widget.TextView;
|
||||
import android.widget.ViewSwitcher.ViewFactory;
|
||||
|
||||
import com.dougkeen.bart.R;
|
||||
import com.dougkeen.bart.controls.CountdownTextView;
|
||||
import com.dougkeen.bart.controls.TimedTextSwitcher;
|
||||
import com.dougkeen.bart.model.Departure;
|
||||
import com.dougkeen.bart.model.TextProvider;
|
||||
|
||||
public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
|
||||
|
||||
public DepartureArrayAdapter(Context context, int textViewResourceId,
|
||||
Departure[] objects) {
|
||||
super(context, textViewResourceId, objects);
|
||||
}
|
||||
|
||||
public DepartureArrayAdapter(Context context, int resource,
|
||||
int textViewResourceId, Departure[] objects) {
|
||||
super(context, resource, textViewResourceId, objects);
|
||||
}
|
||||
|
||||
public DepartureArrayAdapter(Context context, int resource,
|
||||
int textViewResourceId, List<Departure> objects) {
|
||||
super(context, resource, textViewResourceId, objects);
|
||||
}
|
||||
|
||||
public DepartureArrayAdapter(Context context, int resource,
|
||||
int textViewResourceId) {
|
||||
super(context, resource, textViewResourceId);
|
||||
}
|
||||
|
||||
public DepartureArrayAdapter(Context context, int textViewResourceId,
|
||||
List<Departure> objects) {
|
||||
super(context, textViewResourceId, objects);
|
||||
}
|
||||
|
||||
public DepartureArrayAdapter(Context context, int textViewResourceId) {
|
||||
super(context, textViewResourceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View view;
|
||||
if (convertView != null && convertView instanceof RelativeLayout) {
|
||||
view = convertView;
|
||||
} else {
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
view = inflater.inflate(R.layout.departure_listing, parent, false);
|
||||
}
|
||||
|
||||
final Departure departure = getItem(position);
|
||||
((TextView) view.findViewById(R.id.destinationText)).setText(departure
|
||||
.getTrainDestination().toString());
|
||||
|
||||
TimedTextSwitcher textSwitcher = (TimedTextSwitcher) view
|
||||
.findViewById(R.id.trainLengthText);
|
||||
initTextSwitcher(textSwitcher);
|
||||
|
||||
final String estimatedArrivalTimeText = departure
|
||||
.getEstimatedArrivalTimeText(getContext());
|
||||
if (!StringUtils.isBlank(estimatedArrivalTimeText)) {
|
||||
textSwitcher.setCurrentText("Est. arrival "
|
||||
+ estimatedArrivalTimeText);
|
||||
} else {
|
||||
textSwitcher.setCurrentText(departure.getTrainLengthText());
|
||||
}
|
||||
textSwitcher.setTextProvider(new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
if (tickNumber % 4 == 0) {
|
||||
return departure.getTrainLengthText();
|
||||
} else {
|
||||
final String estimatedArrivalTimeText = departure
|
||||
.getEstimatedArrivalTimeText(getContext());
|
||||
if (StringUtils.isBlank(estimatedArrivalTimeText)) {
|
||||
return "";
|
||||
} else {
|
||||
return "Est. arrival " + estimatedArrivalTimeText;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ImageView colorBar = (ImageView) view
|
||||
.findViewById(R.id.destinationColorBar);
|
||||
((GradientDrawable) colorBar.getDrawable()).setColor(Color
|
||||
.parseColor(departure.getTrainDestinationColor()));
|
||||
CountdownTextView countdownTextView = (CountdownTextView) view
|
||||
.findViewById(R.id.countdown);
|
||||
countdownTextView.setText(departure.getCountdownText());
|
||||
countdownTextView.setTextProvider(new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
return departure.getCountdownText();
|
||||
}
|
||||
});
|
||||
((TextView) view.findViewById(R.id.uncertainty)).setText(departure
|
||||
.getUncertaintyText());
|
||||
if (departure.isBikeAllowed()) {
|
||||
((ImageView) view.findViewById(R.id.bikeIcon))
|
||||
.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
((ImageView) view.findViewById(R.id.bikeIcon))
|
||||
.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
if (departure.getRequiresTransfer()) {
|
||||
((ImageView) view.findViewById(R.id.xferIcon))
|
||||
.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
((ImageView) view.findViewById(R.id.xferIcon))
|
||||
.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private void initTextSwitcher(TextSwitcher textSwitcher) {
|
||||
if (textSwitcher.getInAnimation() == null) {
|
||||
textSwitcher.setFactory(new ViewFactory() {
|
||||
public View makeView() {
|
||||
return LayoutInflater.from(getContext()).inflate(
|
||||
R.layout.train_length_arrival_textview, null);
|
||||
}
|
||||
});
|
||||
|
||||
textSwitcher.setInAnimation(AnimationUtils.loadAnimation(
|
||||
getContext(), android.R.anim.slide_in_left));
|
||||
textSwitcher.setOutAnimation(AnimationUtils.loadAnimation(
|
||||
getContext(), android.R.anim.slide_out_right));
|
||||
}
|
||||
}
|
||||
}
|
276
src/com/dougkeen/bart/data/FavoritesArrayAdapter.java
Normal file
276
src/com/dougkeen/bart/data/FavoritesArrayAdapter.java
Normal file
@ -0,0 +1,276 @@
|
||||
package com.dougkeen.bart.data;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.database.Cursor;
|
||||
import android.os.IBinder;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextSwitcher;
|
||||
import android.widget.TextView;
|
||||
import android.widget.ViewSwitcher.ViewFactory;
|
||||
|
||||
import com.dougkeen.bart.R;
|
||||
import com.dougkeen.bart.controls.CountdownTextView;
|
||||
import com.dougkeen.bart.controls.TimedTextSwitcher;
|
||||
import com.dougkeen.bart.model.Departure;
|
||||
import com.dougkeen.bart.model.StationPair;
|
||||
import com.dougkeen.bart.model.TextProvider;
|
||||
import com.dougkeen.bart.services.EtdService;
|
||||
import com.dougkeen.bart.services.EtdService.EtdServiceBinder;
|
||||
import com.dougkeen.bart.services.EtdService.EtdServiceListener;
|
||||
|
||||
public class FavoritesArrayAdapter extends ArrayAdapter<StationPair> {
|
||||
|
||||
private boolean mBound = false;
|
||||
|
||||
private EtdService mEtdService;
|
||||
|
||||
private Activity mHostActivity;
|
||||
|
||||
private Map<StationPair, EtdListener> mEtdListeners = new HashMap<StationPair, EtdListener>();
|
||||
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
mEtdService = null;
|
||||
mBound = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
mEtdService = ((EtdServiceBinder) service).getService();
|
||||
mBound = true;
|
||||
if (!isEmpty()) {
|
||||
setUpEtdListeners();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public void setUpEtdListeners() {
|
||||
if (mBound && mEtdService != null) {
|
||||
for (int i = getCount() - 1; i >= 0; i--) {
|
||||
final StationPair item = getItem(i);
|
||||
mEtdListeners.put(item, new EtdListener(item, mEtdService));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clearEtdListeners() {
|
||||
if (mBound && mEtdService != null) {
|
||||
for (EtdListener listener : mEtdListeners.values()) {
|
||||
listener.close(mEtdService);
|
||||
}
|
||||
mEtdListeners.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean areEtdListenersActive() {
|
||||
return !mEtdListeners.isEmpty();
|
||||
}
|
||||
|
||||
public FavoritesArrayAdapter(Context context, int textViewResourceId) {
|
||||
super(context, textViewResourceId);
|
||||
mHostActivity = (Activity) context;
|
||||
mHostActivity.bindService(new Intent(mHostActivity, EtdService.class),
|
||||
mConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (mBound) {
|
||||
mHostActivity.unbindService(mConnection);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(StationPair object) {
|
||||
super.add(object);
|
||||
if (mEtdService != null && mBound) {
|
||||
mEtdListeners.put(object, new EtdListener(object, mEtdService));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(StationPair object) {
|
||||
super.remove(object);
|
||||
if (mEtdListeners.containsKey(object) && mEtdService != null & mBound) {
|
||||
mEtdListeners.get(object).close(mEtdService);
|
||||
mEtdListeners.remove(object);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
clearEtdListeners();
|
||||
}
|
||||
|
||||
public void updateFromCursor(Cursor cursor) {
|
||||
if (!cursor.moveToFirst()) {
|
||||
clear();
|
||||
}
|
||||
for (int i = 0; i < getCount(); i++) {
|
||||
StationPair adapterItem = getItem(i);
|
||||
StationPair cursorItem = StationPair.createFromCursor(cursor);
|
||||
while (!cursorItem.equals(adapterItem)) {
|
||||
remove(adapterItem);
|
||||
if (i < getCount()) {
|
||||
adapterItem = getItem(i);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cursorItem.equals(adapterItem)
|
||||
&& !cursorItem.fareEquals(adapterItem)) {
|
||||
adapterItem.setFare(cursorItem.getFare());
|
||||
adapterItem.setFareLastUpdated(cursorItem.getFareLastUpdated());
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
cursor.moveToNext();
|
||||
}
|
||||
while (!cursor.isAfterLast()) {
|
||||
add(StationPair.createFromCursor(cursor));
|
||||
cursor.moveToNext();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View view;
|
||||
if (convertView != null && convertView instanceof RelativeLayout) {
|
||||
view = convertView;
|
||||
} else {
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
view = inflater.inflate(R.layout.favorite_listing, parent, false);
|
||||
}
|
||||
|
||||
final StationPair pair = getItem(position);
|
||||
|
||||
final EtdListener etdListener = mEtdListeners.get(pair);
|
||||
|
||||
final TimedTextSwitcher uncertaintyTextSwitcher = (TimedTextSwitcher) view
|
||||
.findViewById(R.id.uncertainty);
|
||||
initTextSwitcher(uncertaintyTextSwitcher);
|
||||
|
||||
if (etdListener == null || etdListener.getFirstDeparture() == null) {
|
||||
uncertaintyTextSwitcher.setCurrentText(pair.getFare());
|
||||
} else {
|
||||
CountdownTextView countdownTextView = (CountdownTextView) view
|
||||
.findViewById(R.id.countdownText);
|
||||
countdownTextView.setText(etdListener.getFirstDeparture()
|
||||
.getCountdownText());
|
||||
countdownTextView.setTextProvider(new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
return etdListener.getFirstDeparture().getCountdownText();
|
||||
}
|
||||
});
|
||||
|
||||
final String uncertaintyText = etdListener.getFirstDeparture()
|
||||
.getUncertaintyText();
|
||||
if (!StringUtils.isBlank(uncertaintyText)) {
|
||||
uncertaintyTextSwitcher.setCurrentText(uncertaintyText);
|
||||
} else {
|
||||
uncertaintyTextSwitcher.setCurrentText(pair.getFare());
|
||||
}
|
||||
uncertaintyTextSwitcher.setTextProvider(new TextProvider() {
|
||||
@Override
|
||||
public String getText(long tickNumber) {
|
||||
if (tickNumber % 4 <= 1) {
|
||||
return pair.getFare();
|
||||
} else {
|
||||
return etdListener.getFirstDeparture()
|
||||
.getUncertaintyText();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
((TextView) view.findViewById(R.id.originText)).setText(pair
|
||||
.getOrigin().name);
|
||||
((TextView) view.findViewById(R.id.destinationText)).setText(pair
|
||||
.getDestination().name);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private void initTextSwitcher(TextSwitcher textSwitcher) {
|
||||
if (textSwitcher.getInAnimation() == null) {
|
||||
textSwitcher.setFactory(new ViewFactory() {
|
||||
public View makeView() {
|
||||
return LayoutInflater.from(getContext()).inflate(
|
||||
R.layout.uncertainty_textview, null);
|
||||
}
|
||||
});
|
||||
|
||||
textSwitcher.setInAnimation(AnimationUtils.loadAnimation(
|
||||
getContext(), android.R.anim.slide_in_left));
|
||||
textSwitcher.setOutAnimation(AnimationUtils.loadAnimation(
|
||||
getContext(), android.R.anim.slide_out_right));
|
||||
}
|
||||
}
|
||||
|
||||
private class EtdListener implements EtdServiceListener {
|
||||
|
||||
private final StationPair mStationPair;
|
||||
|
||||
private Departure firstDeparture;
|
||||
|
||||
protected EtdListener(StationPair mStationPair, EtdService etdService) {
|
||||
super();
|
||||
this.mStationPair = mStationPair;
|
||||
etdService.registerListener(this, true);
|
||||
}
|
||||
|
||||
protected void close(EtdService etdService) {
|
||||
etdService.unregisterListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onETDChanged(List<Departure> departures) {
|
||||
for (Departure departure : departures) {
|
||||
if (!departure.hasDeparted()) {
|
||||
if (!departure.equals(firstDeparture)) {
|
||||
firstDeparture = departure;
|
||||
FavoritesArrayAdapter.this.notifyDataSetChanged();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String errorMessage) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestStarted() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestEnded() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public StationPair getStationPair() {
|
||||
return mStationPair;
|
||||
}
|
||||
|
||||
public Departure getFirstDeparture() {
|
||||
return firstDeparture;
|
||||
}
|
||||
}
|
||||
}
|
@ -496,8 +496,10 @@ public class Departure implements Parcelable, Comparable<Departure> {
|
||||
dest.writeLong(arrivalTimeOverride);
|
||||
dest.writeInt(estimatedTripTime);
|
||||
dest.writeInt(line.ordinal());
|
||||
dest.writeBooleanArray(new boolean[] { beganAsDeparted, bikeAllowed,
|
||||
requiresTransfer, transferScheduled });
|
||||
dest.writeByte(beganAsDeparted ? (byte) 1 : (byte) 0);
|
||||
dest.writeByte(bikeAllowed ? (byte) 1 : (byte) 0);
|
||||
dest.writeByte(requiresTransfer ? (byte) 1 : (byte) 0);
|
||||
dest.writeByte(transferScheduled ? (byte) 1 : (byte) 0);
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel in) {
|
||||
@ -516,12 +518,10 @@ public class Departure implements Parcelable, Comparable<Departure> {
|
||||
arrivalTimeOverride = in.readLong();
|
||||
estimatedTripTime = in.readInt();
|
||||
line = Line.values()[in.readInt()];
|
||||
boolean[] bools = new boolean[4];
|
||||
in.readBooleanArray(bools);
|
||||
beganAsDeparted = bools[0];
|
||||
bikeAllowed = bools[1];
|
||||
requiresTransfer = bools[2];
|
||||
transferScheduled = bools[3];
|
||||
beganAsDeparted = in.readByte() == (byte) 1;
|
||||
bikeAllowed = in.readByte() == (byte) 1;
|
||||
requiresTransfer = in.readByte() == (byte) 1;
|
||||
transferScheduled = in.readByte() == (byte) 1;
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<Departure> CREATOR = new Parcelable.Creator<Departure>() {
|
||||
|
@ -10,8 +10,6 @@ public class Route {
|
||||
private boolean requiresTransfer;
|
||||
private Station transferStation;
|
||||
private String direction;
|
||||
private String fare;
|
||||
private Long fareLastUpdated;
|
||||
|
||||
public Station getOrigin() {
|
||||
return origin;
|
||||
@ -69,22 +67,6 @@ public class Route {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public String getFare() {
|
||||
return fare;
|
||||
}
|
||||
|
||||
public void setFare(String fare) {
|
||||
this.fare = fare;
|
||||
}
|
||||
|
||||
public Long getFareLastUpdated() {
|
||||
return fareLastUpdated;
|
||||
}
|
||||
|
||||
public void setFareLastUpdated(Long fareLastUpdated) {
|
||||
this.fareLastUpdated = fareLastUpdated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
@ -100,10 +82,6 @@ public class Route {
|
||||
builder.append(transferStation);
|
||||
builder.append(", direction=");
|
||||
builder.append(direction);
|
||||
builder.append(", fare=");
|
||||
builder.append(fare);
|
||||
builder.append(", fareLastUpdated=");
|
||||
builder.append(fareLastUpdated);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
@ -1,5 +1,11 @@
|
||||
package com.dougkeen.bart.model;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
import com.dougkeen.bart.data.CursorUtils;
|
||||
import com.dougkeen.bart.data.RoutesColumns;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
@ -11,12 +17,39 @@ public class StationPair implements Parcelable {
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
public StationPair(Long id, Station origin, Station destination) {
|
||||
super();
|
||||
this.origin = origin;
|
||||
this.destination = destination;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public StationPair(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public static StationPair createFromCursor(Cursor cursor) {
|
||||
StationPair pair = new StationPair(
|
||||
Station.getByAbbreviation(CursorUtils.getString(cursor,
|
||||
RoutesColumns.FROM_STATION)),
|
||||
Station.getByAbbreviation(CursorUtils.getString(cursor,
|
||||
RoutesColumns.TO_STATION)));
|
||||
pair.id = CursorUtils.getLong(cursor, RoutesColumns._ID);
|
||||
pair.fare = CursorUtils.getString(cursor, RoutesColumns.FARE);
|
||||
pair.fareLastUpdated = CursorUtils.getLong(cursor,
|
||||
RoutesColumns.FARE_LAST_UPDATED);
|
||||
return pair;
|
||||
}
|
||||
|
||||
private Long id;
|
||||
private Station origin;
|
||||
private Station destination;
|
||||
private String fare;
|
||||
private Long fareLastUpdated;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Station getOrigin() {
|
||||
return origin;
|
||||
@ -26,6 +59,22 @@ public class StationPair implements Parcelable {
|
||||
return destination;
|
||||
}
|
||||
|
||||
public String getFare() {
|
||||
return fare;
|
||||
}
|
||||
|
||||
public void setFare(String fare) {
|
||||
this.fare = fare;
|
||||
}
|
||||
|
||||
public Long getFareLastUpdated() {
|
||||
return fareLastUpdated;
|
||||
}
|
||||
|
||||
public void setFareLastUpdated(Long fareLastUpdated) {
|
||||
this.fareLastUpdated = fareLastUpdated;
|
||||
}
|
||||
|
||||
public boolean isBetweenStations(Station station1, Station station2) {
|
||||
return (origin.equals(station1) && destination.equals(station2))
|
||||
|| (origin.equals(station2) && destination.equals(station1));
|
||||
@ -51,6 +100,14 @@ public class StationPair implements Parcelable {
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean fareEquals(StationPair other) {
|
||||
if (other == null)
|
||||
return false;
|
||||
return ObjectUtils.equals(getFare(), other.getFare())
|
||||
&& ObjectUtils.equals(getFareLastUpdated(),
|
||||
other.getFareLastUpdated());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
|
@ -1,4 +1,7 @@
|
||||
package com.dougkeen.bart;
|
||||
package com.dougkeen.bart.receivers;
|
||||
|
||||
import com.dougkeen.bart.BartRunnerApplication;
|
||||
import com.dougkeen.util.WakeLocker;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
@ -1,4 +1,4 @@
|
||||
package com.dougkeen.bart;
|
||||
package com.dougkeen.bart.services;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@ -21,6 +21,8 @@ import android.os.IBinder;
|
||||
import android.support.v4.content.CursorLoader;
|
||||
import android.util.Log;
|
||||
|
||||
import com.dougkeen.bart.BartRunnerApplication;
|
||||
import com.dougkeen.bart.R;
|
||||
import com.dougkeen.bart.data.RoutesColumns;
|
||||
import com.dougkeen.bart.model.Constants;
|
||||
import com.dougkeen.bart.model.Departure;
|
||||
@ -44,7 +46,8 @@ public class EtdService extends Service {
|
||||
mServiceEngineMap = new HashMap<StationPair, EtdServiceEngine>();
|
||||
}
|
||||
|
||||
public void registerListener(EtdServiceListener listener) {
|
||||
public void registerListener(EtdServiceListener listener,
|
||||
boolean limitToFirstNonDeparted) {
|
||||
StationPair stationPair = getStationPairFromListener(listener);
|
||||
if (stationPair == null)
|
||||
return;
|
||||
@ -53,7 +56,8 @@ public class EtdService extends Service {
|
||||
mServiceEngineMap.put(stationPair,
|
||||
new EtdServiceEngine(stationPair));
|
||||
}
|
||||
mServiceEngineMap.get(stationPair).registerListener(listener);
|
||||
mServiceEngineMap.get(stationPair).registerListener(listener,
|
||||
limitToFirstNonDeparted);
|
||||
}
|
||||
|
||||
private StationPair getStationPairFromListener(EtdServiceListener listener) {
|
||||
@ -116,6 +120,8 @@ public class EtdService extends Service {
|
||||
// We'll only use the keys
|
||||
private WeakHashMap<EtdServiceListener, Boolean> mListeners;
|
||||
|
||||
private boolean mLimitToFirstNonDeparted = true;
|
||||
|
||||
private List<Departure> mLatestDepartures;
|
||||
private ScheduleInformation mLatestScheduleInfo;
|
||||
|
||||
@ -148,8 +154,11 @@ public class EtdService extends Service {
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
protected void registerListener(EtdServiceListener listener) {
|
||||
protected void registerListener(EtdServiceListener listener,
|
||||
boolean limitToFirstNonDeparted) {
|
||||
mListeners.put(listener, true);
|
||||
if (!limitToFirstNonDeparted)
|
||||
mLimitToFirstNonDeparted = false;
|
||||
if (!mPendingEtdRequest) {
|
||||
mStarted = true;
|
||||
fetchLatestDepartures();
|
||||
@ -439,6 +448,9 @@ public class EtdService extends Service {
|
||||
if (departure.equals(boardedDeparture)) {
|
||||
boardedDeparture.mergeEstimate(departure);
|
||||
}
|
||||
if (!departure.hasDeparted() && mLimitToFirstNonDeparted) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -504,6 +516,10 @@ public class EtdService extends Service {
|
||||
if (departure.equals(boardedDeparture)) {
|
||||
boardedDeparture.mergeEstimate(departure);
|
||||
}
|
||||
|
||||
if (!departure.hasDeparted() && mLimitToFirstNonDeparted) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Collections.sort(mLatestDepartures);
|
@ -1,4 +1,4 @@
|
||||
package com.dougkeen.bart;
|
||||
package com.dougkeen.bart.services;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -18,17 +18,19 @@ import android.os.HandlerThread;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.Parcelable;
|
||||
import android.os.SystemClock;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.app.NotificationCompat.Builder;
|
||||
import android.util.Log;
|
||||
import android.util.TimeFormatException;
|
||||
|
||||
import com.dougkeen.bart.EtdService.EtdServiceBinder;
|
||||
import com.dougkeen.bart.EtdService.EtdServiceListener;
|
||||
import com.dougkeen.bart.BartRunnerApplication;
|
||||
import com.dougkeen.bart.R;
|
||||
import com.dougkeen.bart.model.Constants;
|
||||
import com.dougkeen.bart.model.Departure;
|
||||
import com.dougkeen.bart.model.StationPair;
|
||||
import com.dougkeen.bart.services.EtdService.EtdServiceBinder;
|
||||
import com.dougkeen.bart.services.EtdService.EtdServiceListener;
|
||||
|
||||
public class NotificationService extends Service implements EtdServiceListener {
|
||||
|
||||
@ -74,7 +76,7 @@ public class NotificationService extends Service implements EtdServiceListener {
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
mEtdService = ((EtdServiceBinder) service).getService();
|
||||
if (getStationPair() != null) {
|
||||
mEtdService.registerListener(NotificationService.this);
|
||||
mEtdService.registerListener(NotificationService.this, false);
|
||||
}
|
||||
mBound = true;
|
||||
}
|
||||
@ -142,7 +144,7 @@ public class NotificationService extends Service implements EtdServiceListener {
|
||||
}
|
||||
|
||||
if (getStationPair() != null && mEtdService != null) {
|
||||
mEtdService.registerListener(this);
|
||||
mEtdService.registerListener(this, false);
|
||||
}
|
||||
|
||||
Intent targetIntent = new Intent(Intent.ACTION_VIEW,
|
||||
@ -163,7 +165,7 @@ public class NotificationService extends Service implements EtdServiceListener {
|
||||
getStationPair().getUri());
|
||||
final Departure boardedDeparture = ((BartRunnerApplication) getApplication())
|
||||
.getBoardedDeparture();
|
||||
alarmIntent.putExtra("departure", boardedDeparture);
|
||||
alarmIntent.putExtra("departure", (Parcelable) boardedDeparture);
|
||||
mAlarmPendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
@ -317,7 +319,7 @@ public class NotificationService extends Service implements EtdServiceListener {
|
||||
mStationPair.getOrigin().shortName + " to "
|
||||
+ mStationPair.getDestination().shortName)
|
||||
.setContentIntent(mNotificationIntent).setWhen(0);
|
||||
if (android.os.Build.VERSION.SDK_INT > 16) {
|
||||
if (android.os.Build.VERSION.SDK_INT >= 16) {
|
||||
notificationBuilder
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
.addAction(
|
@ -1,4 +1,4 @@
|
||||
package com.dougkeen.bart;
|
||||
package com.dougkeen.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.PowerManager;
|
Loading…
Reference in New Issue
Block a user