Implemented alarm canceling

This commit is contained in:
Doug Keen 2012-09-19 14:12:18 -07:00
parent 98b4cf84f7
commit fae89f4c45
15 changed files with 606 additions and 33 deletions

438
cancelAlarm.svg Normal file
View File

@ -0,0 +1,438 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg2"
version="1.1"
inkscape:version="0.48.2 r9819"
width="120"
height="120"
xml:space="preserve"
sodipodi:docname="cancelAlarm.svg"><metadata
id="metadata8"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs6"><linearGradient
x1="0"
y1="0"
x2="1"
y2="0"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0,96,96,0,48,0)"
spreadMethod="pad"
id="linearGradient24"><stop
style="stop-opacity:1;stop-color:#272d33"
offset="0"
id="stop26" /><stop
style="stop-opacity:1;stop-color:#000000"
offset="1"
id="stop28" /></linearGradient><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath38"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path40" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath50"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path52" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath62"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path64" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath74"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path76" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath90"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path92" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath100"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path102" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath110"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path112" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath122"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path124" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath138"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path140" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath148"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path150" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath176"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path178" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath200"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path202" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath216"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path218" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath232"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path234" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath252"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path254" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath268"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path270" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath278"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path280" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath302"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path304" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath324"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path326" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath344"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path346" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath356"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path358" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath380"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path382" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath392"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path394" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath404"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path406" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath416"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path418" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath428"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path430" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath440"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path442" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath456"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path458" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath468"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path470" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath492"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path494" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath504"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path506" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath516"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path518" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath532"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path534" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath544"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path546" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath560"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path562" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath572"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path574" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath584"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path586" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath600"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path602" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath612"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path614" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath626"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path628" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath638"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path640" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath650"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path652" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath662"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path664" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath714"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path716" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath730"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path732" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath778"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path780" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath794"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path796" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath810"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path812" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath832"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path834" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath848"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path850" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath904"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path906" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath920"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path922" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath930"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path932" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath942"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path944" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath958"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path960" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath974"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path976" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath990"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path992" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1022"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1024" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1038"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1040" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1054"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1056" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1066"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1068" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1080"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1082" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1096"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1098" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1108"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1110" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1128"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1130" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1178"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1180" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1210"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1212" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1224"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1226" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1244"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1246" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1256"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1258" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1272"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1274" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1284"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1286" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1300"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1302" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1310"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1312" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1342"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1344" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1354"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1356" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1394"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1396" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1426"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1428" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1446"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1448" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1458"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1460" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1470"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1472" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1494"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1496" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1512"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1514" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1524"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1526" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1534"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1536" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1562"><path
d="M 0,96 96,96 96,0 0,0 0,96 z"
id="path1564" /></clipPath></defs><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1053"
id="namedview4"
showgrid="false"
inkscape:zoom="5.5625733"
inkscape:cx="244.15273"
inkscape:cy="47.072123"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="g10" /><g
id="g10"
inkscape:groupmode="layer"
inkscape:label="All_Icons"
transform="matrix(1.25,0,0,-1.25,0,120)"><g
style="fill:#ffffff;fill-opacity:1"
id="g152"
transform="translate(64.589027,64.538954)"><path
d="m 0,0 2.951,1.057 c -2.383,5.942 -7,10.737 -12.82,13.355 l -1.067,-2.968 C -5.99,9.151 -2.059,5.061 0,0"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
id="path154"
inkscape:connector-curvature="0" /></g><g
style="fill:#ffffff;fill-opacity:1"
id="g156"
transform="translate(35.560727,75.983254)"><path
d="m 0,0 -1.063,2.968 c -5.926,-2.664 -10.599,-7.591 -12.94,-13.686 l 2.951,-1.055 C -9.03,-6.563 -5.048,-2.338 0,0"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
id="path158"
inkscape:connector-curvature="0" /></g><g
style="fill:#ffffff;fill-opacity:1"
id="g164"
transform="translate(44.606127,40.926554)"><path
d="m 0,0 c -8.551,0 -15.484,6.933 -15.484,15.486 0,8.551 6.933,15.486 15.484,15.486 8.554,0 15.487,-6.935 15.487,-15.486 C 15.487,6.933 8.554,0 0,0 m 0,33.93 c -10.188,0 -18.443,-8.257 -18.443,-18.444 0,-10.187 8.255,-18.444 18.443,-18.444 10.188,0 18.447,8.257 18.447,18.444 C 18.447,25.673 10.188,33.93 0,33.93"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path166"
inkscape:connector-curvature="0" /></g><g
style="fill:#ffffff;fill-opacity:1"
id="g168"
transform="translate(44.919127,68.907554)"><path
d="m 0,0 -1.958,0 -0.675,-12.603 0.175,-1.318 9.427,-8.387 1.489,1.527 -7.795,8.355 L 0,0 z"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path170"
inkscape:connector-curvature="0" /></g><g
style="fill:#ffffff;fill-opacity:1"
id="g524"
transform="matrix(1.0643339,0,0,1.0577275,80.62467,39.900995)"><path
d="m 0,0 0.24,0.244 -2.894,2.91 -8.28,-8.304 -8.033,8.064 -0.244,0.24 -2.9,-2.91 8.281,-8.299 -8.039,-8.06 -0.242,-0.242 2.9,-2.911 8.277,8.305 8.036,-8.06 0.244,-0.245 2.898,2.911 -8.279,8.302 L 0,0 z"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path526"
inkscape:connector-curvature="0" /></g></g></svg>

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 595 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 856 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -97,7 +97,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:indeterminate="true" android:indeterminate="true"
android:visibility="invisible" /> android:visibility="invisible" />
<TextView
<TextView
android:id="@android:id/empty" android:id="@android:id/empty"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -1,16 +1,22 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" > <menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/cancel_alarm_button"
android:icon="@drawable/ic_action_cancel_alarm"
android:showAsAction="always|withText"
android:title="Cancel alarm"
android:visible="false"/>
<item <item
android:id="@+id/view_on_bart_site_button" android:id="@+id/view_on_bart_site_button"
android:icon="@drawable/ic_action_web" android:icon="@drawable/ic_action_web"
android:showAsAction="ifRoom|withText" android:showAsAction="always|withText"
android:title="@string/view_on_bart_site"> android:title="@string/view_on_bart_site">
</item> </item>
<item <item
android:id="@+id/view_system_map_button" android:id="@+id/view_system_map_button"
android:icon="@drawable/ic_action_map" android:icon="@drawable/ic_action_map"
android:showAsAction="ifRoom|withText" android:showAsAction="always|withText"
android:title="@string/view_system_map"> android:title="@string/view_system_map">
</item> </item>

View File

@ -19,6 +19,8 @@ public class AlarmBroadcastReceiver extends BroadcastReceiver {
targetIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); targetIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(targetIntent); context.startActivity(targetIntent);
application.setAlarmPending(false);
} }
} }

View File

@ -4,10 +4,13 @@ import android.app.Application;
import android.media.MediaPlayer; import android.media.MediaPlayer;
import com.dougkeen.bart.model.Departure; import com.dougkeen.bart.model.Departure;
import com.dougkeen.util.Observable;
public class BartRunnerApplication extends Application { public class BartRunnerApplication extends Application {
private Departure mBoardedDeparture; private Departure mBoardedDeparture;
private Observable<Boolean> mAlarmPending = new Observable<Boolean>(false);
private boolean mPlayAlarmRingtone; private boolean mPlayAlarmRingtone;
private boolean mAlarmSounding; private boolean mAlarmSounding;
@ -46,4 +49,16 @@ public class BartRunnerApplication extends Application {
this.mAlarmMediaPlayer = alarmMediaPlayer; this.mAlarmMediaPlayer = alarmMediaPlayer;
} }
public boolean isAlarmPending() {
return mAlarmPending.getValue();
}
public Observable<Boolean> getAlarmPendingObservable() {
return mAlarmPending;
}
public void setAlarmPending(boolean alarmPending) {
this.mAlarmPending.setValue(alarmPending);
}
} }

View File

@ -67,10 +67,11 @@ public class EtdService extends Service {
public void unregisterListener(EtdServiceListener listener) { public void unregisterListener(EtdServiceListener listener) {
StationPair stationPair = getStationPairFromListener(listener); StationPair stationPair = getStationPairFromListener(listener);
if (stationPair == null) if (stationPair == null) {
return; for (EtdServiceEngine engine : mServiceEngineMap.values()) {
engine.unregisterListener(listener);
if (mServiceEngineMap.containsKey(stationPair)) { }
} else if (mServiceEngineMap.containsKey(stationPair)) {
mServiceEngineMap.get(stationPair).unregisterListener(listener); mServiceEngineMap.get(stationPair).unregisterListener(listener);
} }
} }
@ -93,7 +94,6 @@ public class EtdService extends Service {
} }
public class EtdServiceBinder extends Binder { public class EtdServiceBinder extends Binder {
public EtdService getService() { public EtdService getService() {
return EtdService.this; return EtdService.this;
} }
@ -210,9 +210,9 @@ public class EtdService extends Service {
mIgnoreDepartureDirection) { mIgnoreDepartureDirection) {
@Override @Override
public void onResult(RealTimeDepartures result) { public void onResult(RealTimeDepartures result) {
Log.d(Constants.TAG, "Processing data from server"); Log.v(Constants.TAG, "Processing data from server");
processLatestDepartures(result); processLatestDepartures(result);
Log.d(Constants.TAG, "Done processing data from server"); Log.v(Constants.TAG, "Done processing data from server");
notifyListenersOfRequestEnd(); notifyListenersOfRequestEnd();
mPendingEtdRequest = false; mPendingEtdRequest = false;
} }
@ -227,7 +227,7 @@ public class EtdService extends Service {
} }
}; };
mGetDeparturesTask = task; mGetDeparturesTask = task;
Log.d(Constants.TAG, "Fetching data from server"); Log.v(Constants.TAG, "Fetching data from server");
task.execute(new StationPair(mStationPair.getOrigin(), mStationPair task.execute(new StationPair(mStationPair.getOrigin(), mStationPair
.getDestination())); .getDestination()));
notifyListenersOfRequestStart(); notifyListenersOfRequestStart();
@ -244,10 +244,10 @@ public class EtdService extends Service {
GetScheduleInformationTask task = new GetScheduleInformationTask() { GetScheduleInformationTask task = new GetScheduleInformationTask() {
@Override @Override
public void onResult(ScheduleInformation result) { public void onResult(ScheduleInformation result) {
Log.d(Constants.TAG, "Processing data from server"); Log.v(Constants.TAG, "Processing data from server");
mLatestScheduleInfo = result; mLatestScheduleInfo = result;
applyScheduleInformation(result); applyScheduleInformation(result);
Log.d(Constants.TAG, "Done processing data from server"); Log.v(Constants.TAG, "Done processing data from server");
} }
@Override @Override
@ -299,8 +299,8 @@ public class EtdService extends Service {
ScheduleItem trip = mLatestScheduleInfo.getTrips().get(i); ScheduleItem trip = mLatestScheduleInfo.getTrips().get(i);
// Definitely not a match if they have different // Definitely not a match if they have different
// destinations // destinations
if (!departure.getTrainDestination().abbreviation.equals(trip if (!departure.getTrainDestination().abbreviation
.getTrainHeadStation())) { .equals(trip.getTrainHeadStation())) {
continue; continue;
} }
@ -582,7 +582,7 @@ public class EtdService extends Service {
} }
}, millisUntilExecute); }, millisUntilExecute);
mNextFetchClockTime = requestedFetchTime; mNextFetchClockTime = requestedFetchTime;
Log.d(Constants.TAG, "Scheduled another departure fetch in " Log.i(Constants.TAG, "Scheduled another departure fetch in "
+ millisUntilExecute / 1000 + "s"); + millisUntilExecute / 1000 + "s");
} }
} }
@ -593,7 +593,7 @@ public class EtdService extends Service {
fetchLatestSchedule(); fetchLatestSchedule();
} }
}, millisUntilExecute); }, millisUntilExecute);
Log.d(Constants.TAG, "Scheduled another schedule fetch in " Log.i(Constants.TAG, "Scheduled another schedule fetch in "
+ millisUntilExecute / 1000 + "s"); + millisUntilExecute / 1000 + "s");
} }

View File

@ -2,6 +2,8 @@ package com.dougkeen.bart;
import java.util.List; import java.util.List;
import org.apache.commons.lang3.time.DateFormatUtils;
import android.app.AlarmManager; import android.app.AlarmManager;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
@ -19,6 +21,8 @@ import android.os.Message;
import android.os.SystemClock; import android.os.SystemClock;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.Builder; 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.EtdServiceBinder;
import com.dougkeen.bart.EtdService.EtdServiceListener; import com.dougkeen.bart.EtdService.EtdServiceListener;
@ -103,6 +107,7 @@ public class NotificationService extends Service implements EtdServiceListener {
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
mHasShutDown = false;
onStart(intent, startId); onStart(intent, startId);
return START_STICKY; return START_STICKY;
} }
@ -119,8 +124,9 @@ public class NotificationService extends Service implements EtdServiceListener {
protected void onHandleIntent(Intent intent) { protected void onHandleIntent(Intent intent) {
final Departure boardedDeparture = ((BartRunnerApplication) getApplication()) final Departure boardedDeparture = ((BartRunnerApplication) getApplication())
.getBoardedDeparture(); .getBoardedDeparture();
if (boardedDeparture == null) { if (boardedDeparture == null
// Nothing to notify about || intent.getBooleanExtra("cancelAlarm", false)) {
// Nothing to notify about, or we want to cancel the alarm
shutDown(false); shutDown(false);
return; return;
} }
@ -139,14 +145,14 @@ public class NotificationService extends Service implements EtdServiceListener {
mEtdService.registerListener(this); mEtdService.registerListener(this);
} }
updateNotification();
Intent targetIntent = new Intent(Intent.ACTION_VIEW, Intent targetIntent = new Intent(Intent.ACTION_VIEW,
mStationPair.getUri()); mStationPair.getUri());
targetIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); targetIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mNotificationIntent = PendingIntent.getActivity(this, 0, targetIntent, mNotificationIntent = PendingIntent.getActivity(this, 0, targetIntent,
PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent.FLAG_UPDATE_CURRENT);
updateNotification();
setAlarm(); setAlarm();
pollDepartureStatus(); pollDepartureStatus();
@ -168,14 +174,20 @@ public class NotificationService extends Service implements EtdServiceListener {
if (mAlertLeadTime > 0) { if (mAlertLeadTime > 0) {
long alertTime = getAlarmClockTime(); long alertTime = getAlarmClockTime();
if (alertTime > System.currentTimeMillis()) { if (alertTime > System.currentTimeMillis()) {
if (Log.isLoggable(Constants.TAG, Log.VERBOSE))
Log.v(Constants.TAG, "Scheduling alarm for "
+ DateFormatUtils.format(alertTime, "h:mm:ss"));
refreshAlarmPendingIntent(); refreshAlarmPendingIntent();
mAlarmManager.set(AlarmManager.RTC_WAKEUP, alertTime, mAlarmManager.set(AlarmManager.RTC_WAKEUP, alertTime,
mAlarmPendingIntent); mAlarmPendingIntent);
((BartRunnerApplication) getApplication())
.setAlarmPending(true);
} }
} }
} }
private void triggerAlarmImmediately() { private void triggerAlarmImmediately() {
Log.v(Constants.TAG, "Setting off alarm immediately");
cancelAlarm(); cancelAlarm();
refreshAlarmPendingIntent(); refreshAlarmPendingIntent();
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
@ -189,6 +201,7 @@ public class NotificationService extends Service implements EtdServiceListener {
} }
private void cancelAlarm() { private void cancelAlarm() {
((BartRunnerApplication) getApplication()).setAlarmPending(false);
mAlarmManager.cancel(mAlarmPendingIntent); mAlarmManager.cancel(mAlarmPendingIntent);
} }
@ -280,7 +293,9 @@ public class NotificationService extends Service implements EtdServiceListener {
private void updateNotification() { private void updateNotification() {
if (mHasShutDown) { if (mHasShutDown) {
mNotificationManager.cancel(DEPARTURE_NOTIFICATION_ID); if (mEtdService != null) {
mEtdService.unregisterListener(this);
}
return; return;
} }
@ -292,16 +307,35 @@ public class NotificationService extends Service implements EtdServiceListener {
: (String.format("~%.1f minute", minutes) + ((minutes != 1.0) ? "s" : (String.format("~%.1f minute", minutes) + ((minutes != 1.0) ? "s"
: "")); : ""));
final Intent cancelAlarmIntent = new Intent(getApplicationContext(),
NotificationService.class);
cancelAlarmIntent.putExtra("cancelAlarm", true);
Builder notificationBuilder = new NotificationCompat.Builder(this) Builder notificationBuilder = new NotificationCompat.Builder(this)
.setOngoing(true) .setOngoing(true)
.setSmallIcon(R.drawable.ic_stat_notification) .setSmallIcon(R.drawable.ic_stat_notification)
.setContentTitle( .setContentTitle(
mStationPair.getOrigin().shortName + " to " mStationPair.getOrigin().shortName + " to "
+ mStationPair.getDestination().shortName) + mStationPair.getDestination().shortName)
.setContentText(minutesText + " until departure")
.setSubText(
"Alert " + mAlertLeadTime + " minutes before departure")
.setContentIntent(mNotificationIntent).setWhen(0); .setContentIntent(mNotificationIntent).setWhen(0);
if (android.os.Build.VERSION.SDK_INT > 16) {
notificationBuilder
.setPriority(NotificationCompat.PRIORITY_HIGH)
.addAction(
R.drawable.ic_action_cancel_alarm,
"Cancel alarm",
PendingIntent.getService(getApplicationContext(),
0, cancelAlarmIntent,
PendingIntent.FLAG_UPDATE_CURRENT))
.setContentText(minutesText + " until departure")
.setSubText(
"Alert " + mAlertLeadTime
+ " minutes before departure");
} else {
notificationBuilder.setContentText(minutesText
+ " to departure (alarm at " + mAlertLeadTime + " min"
+ ((mAlertLeadTime == 1) ? "" : "s") + ")");
}
mNotificationManager.notify(DEPARTURE_NOTIFICATION_ID, mNotificationManager.notify(DEPARTURE_NOTIFICATION_ID,
notificationBuilder.build()); notificationBuilder.build());
} }
@ -318,11 +352,7 @@ public class NotificationService extends Service implements EtdServiceListener {
return 10000000; // Arbitrarily large number return 10000000; // Arbitrarily large number
} }
if (secondsToAlarm > 10 * 60) { if (secondsToAlarm > 3 * 60) {
return 60 * 1000;
} else if (secondsToAlarm > 5 * 60) {
return 60 * 1000;
} else if (secondsToAlarm > 3 * 60) {
return 30 * 1000; return 30 * 1000;
} else { } else {
return 10 * 1000; return 10 * 1000;

View File

@ -82,8 +82,7 @@ public class TrainAlertDialogFragment extends DialogFragment {
alertLeadTime); alertLeadTime);
editor.commit(); editor.commit();
Intent intent = new Intent(getActivity() Intent intent = new Intent(getActivity(),
.getApplicationContext(),
NotificationService.class); NotificationService.class);
intent.putExtra("alertLeadTime", alertLeadTime); intent.putExtra("alertLeadTime", alertLeadTime);
getActivity().startService(intent); getActivity().startService(intent);

View File

@ -49,6 +49,7 @@ import com.dougkeen.bart.model.Departure;
import com.dougkeen.bart.model.Station; import com.dougkeen.bart.model.Station;
import com.dougkeen.bart.model.StationPair; import com.dougkeen.bart.model.StationPair;
import com.dougkeen.bart.model.TextProvider; import com.dougkeen.bart.model.TextProvider;
import com.dougkeen.util.Observer;
public class ViewDeparturesActivity extends SherlockFragmentActivity implements public class ViewDeparturesActivity extends SherlockFragmentActivity implements
EtdServiceListener { EtdServiceListener {
@ -291,6 +292,8 @@ public class ViewDeparturesActivity extends SherlockFragmentActivity implements
} }
}; };
private Observer<Boolean> mAlarmPendingObserver;
protected DepartureArrayAdapter getListAdapter() { protected DepartureArrayAdapter getListAdapter() {
return mDeparturesAdapter; return mDeparturesAdapter;
} }
@ -305,6 +308,10 @@ public class ViewDeparturesActivity extends SherlockFragmentActivity implements
super.onStop(); super.onStop();
if (mEtdService != null) if (mEtdService != null)
mEtdService.unregisterListener(this); mEtdService.unregisterListener(this);
if (mAlarmPendingObserver != null)
((BartRunnerApplication) getApplication())
.getAlarmPendingObservable().unregisterObserver(
mAlarmPendingObserver);
if (mBound) if (mBound)
unbindService(mConnection); unbindService(mConnection);
Ticker.getInstance().stopTicking(); Ticker.getInstance().stopTicking();
@ -355,6 +362,25 @@ public class ViewDeparturesActivity extends SherlockFragmentActivity implements
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getSupportMenuInflater(); MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.route_menu, menu); inflater.inflate(R.menu.route_menu, menu);
final MenuItem cancelAlarmButton = menu
.findItem(R.id.cancel_alarm_button);
final BartRunnerApplication application = (BartRunnerApplication) getApplication();
if (application.isAlarmPending()) {
cancelAlarmButton.setVisible(true);
}
mAlarmPendingObserver = new Observer<Boolean>() {
@Override
public void onUpdate(final Boolean newValue) {
runOnUiThread(new Runnable() {
@Override
public void run() {
cancelAlarmButton.setVisible(newValue);
}
});
}
};
application.getAlarmPendingObservable().registerObserver(
mAlarmPendingObserver);
return true; return true;
} }
@ -367,6 +393,11 @@ public class ViewDeparturesActivity extends SherlockFragmentActivity implements
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent); startActivity(intent);
return true; return true;
} else if (itemId == R.id.cancel_alarm_button) {
Intent intent = new Intent(this, NotificationService.class);
intent.putExtra("cancelAlarm", true);
startService(intent);
return true;
} else if (itemId == R.id.view_on_bart_site_button) { } else if (itemId == R.id.view_on_bart_site_button) {
startActivity(new Intent( startActivity(new Intent(
Intent.ACTION_VIEW, Intent.ACTION_VIEW,
@ -477,7 +508,7 @@ public class ViewDeparturesActivity extends SherlockFragmentActivity implements
refreshBoardedDeparture(); refreshBoardedDeparture();
// Stop the notification service // Stop the notification service
stopService(new Intent(getApplicationContext(), stopService(new Intent(ViewDeparturesActivity.this,
NotificationService.class)); NotificationService.class));
// Don't prompt for alert if train is about to leave // Don't prompt for alert if train is about to leave

View File

@ -0,0 +1,46 @@
package com.dougkeen.util;
import java.util.WeakHashMap;
import org.apache.commons.lang3.ObjectUtils;
public class Observable<T> {
private T value;
private WeakHashMap<Observer<T>, Boolean> listeners = new WeakHashMap<Observer<T>, Boolean>();
public Observable() {
super();
}
public Observable(T value) {
super();
this.value = value;
}
public T getValue() {
return value;
}
public void setValue(T value) {
if (!ObjectUtils.equals(this.value, value)) {
this.value = value;
notifyOfChange(value);
}
}
public void registerObserver(Observer<T> observer) {
listeners.put(observer, true);
}
public void unregisterObserver(Observer<T> observer) {
listeners.remove(observer);
}
protected void notifyOfChange(T value) {
for (Observer<T> listener : listeners.keySet()) {
if (listener != null) {
listener.onUpdate(value);
}
}
}
}

View File

@ -0,0 +1,5 @@
package com.dougkeen.util;
public interface Observer<T> {
void onUpdate(final T newValue);
}