From 2bb1b5d0351627868900ed9835153d18dd0619dc Mon Sep 17 00:00:00 2001 From: dkeen Date: Fri, 27 May 2011 14:06:58 -0700 Subject: [PATCH] Added bike and xfer icons. Now more well-behaved when switching orientations. Added option to view routes on m.bart.gov --HG-- rename : res/menu/favorite_context_menu.xml => res/menu/route_context_menu.xml rename : res/menu/favorites_menu.xml => res/menu/routes_list_menu.xml rename : src/com/dougkeen/bart/AddFavoriteActivity.java => src/com/dougkeen/bart/AddRouteActivity.java rename : src/com/dougkeen/bart/FavoritesDashboardActivity.java => src/com/dougkeen/bart/RoutesListActivity.java rename : src/com/dougkeen/bart/data/FavoritesColumns.java => src/com/dougkeen/bart/data/RoutesColumns.java --- .hgignore | 8 +- AndroidManifest.xml | 6 +- res/drawable-hdpi/icon.png | Bin 4147 -> 3826 bytes res/drawable-ldpi/icon.png | Bin 1723 -> 1795 bytes res/drawable-mdpi/icon.png | Bin 2574 -> 2534 bytes res/drawable/basic_rectangle.xml | 2 +- res/drawable/bike.png | Bin 0 -> 1008 bytes res/drawable/xfer.png | Bin 0 -> 839 bytes res/layout/add_favorite.xml | 2 +- res/layout/arrival_listing.xml | 20 +++- res/layout/simple_spinner_item.xml | 2 +- ...ontext_menu.xml => route_context_menu.xml} | 0 res/menu/route_menu.xml | 5 + ...avorites_menu.xml => routes_list_menu.xml} | 2 +- res/values/strings.xml | 19 +-- res/values/styles.xml | 30 ++++- ...iteActivity.java => AddRouteActivity.java} | 8 +- .../dougkeen/bart/ArrivalArrayAdapter.java | 90 ++++++++++++++ .../bart/GetRealTimeArrivalsTask.java | 9 +- src/com/dougkeen/bart/Route.java | 11 ++ ...dActivity.java => RoutesListActivity.java} | 38 +++--- src/com/dougkeen/bart/Station.java | 16 ++- .../dougkeen/bart/ViewArrivalsActivity.java | 110 +++++++++++++++--- src/com/dougkeen/bart/data/Arrival.java | 107 ++++++++++++++--- .../bart/data/BartContentProvider.java | 30 ++--- src/com/dougkeen/bart/data/CursorUtils.java | 2 +- .../dougkeen/bart/data/DatabaseHelper.java | 6 +- ...voritesColumns.java => RoutesColumns.java} | 4 +- xfer.svg | 109 +++++++++++++++++ 29 files changed, 534 insertions(+), 102 deletions(-) create mode 100644 res/drawable/bike.png create mode 100644 res/drawable/xfer.png rename res/menu/{favorite_context_menu.xml => route_context_menu.xml} (100%) create mode 100644 res/menu/route_menu.xml rename res/menu/{favorites_menu.xml => routes_list_menu.xml} (64%) rename src/com/dougkeen/bart/{AddFavoriteActivity.java => AddRouteActivity.java} (87%) create mode 100644 src/com/dougkeen/bart/ArrivalArrayAdapter.java rename src/com/dougkeen/bart/{FavoritesDashboardActivity.java => RoutesListActivity.java} (89%) rename src/com/dougkeen/bart/data/{FavoritesColumns.java => RoutesColumns.java} (77%) create mode 100644 xfer.svg diff --git a/.hgignore b/.hgignore index 60aefa5..0c40d8c 100644 --- a/.hgignore +++ b/.hgignore @@ -1,3 +1,9 @@ syntax: glob -bin/* \ No newline at end of file +bin/* +syntax: regexp +^app_icon\.psd$ +syntax: regexp +^bart-train\.jpg$ +syntax: regexp +^colorscheme\.jpg$ \ No newline at end of file diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 6032628..9f860fa 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,6 +1,6 @@ @@ -9,7 +9,7 @@ - @@ -28,7 +28,7 @@ - + diff --git a/res/drawable-hdpi/icon.png b/res/drawable-hdpi/icon.png index 8074c4c571b8cd19e27f4ee5545df367420686d7..a5c7cbd6559decf9a178379bdc71a66a0c0e0ffe 100644 GIT binary patch literal 3826 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 literal 4147 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 diff --git a/res/drawable-ldpi/icon.png b/res/drawable-ldpi/icon.png index 1095584ec21f71cd0afc9e0993aa2209671b590c..2929050657c80d55a48e89b0a7d679073c47e572 100644 GIT binary patch delta 1780 zcmVQw_r*%mWK-buL*RYG3I4dVAZlU2dC_%%aWF(7C|qvJd|}eN+(O zvx!8EAk3R14s_JU~`^ESu;N)#Dq z2Zpzvx)FFRPt>E)xT9}$e4Rq1STE`GJPgp{nTv3FIQV#;hE&~f>YC;>4HNnuiYTTC zQ|I8y3W(Z-q3Nd1P~WK-CqrbDyl0pNqs-7X8WtdPQh!9#AVaM@Am zcEU^NQilyCHU)|#L6QWJ$C081MG`3lV+jPpQ4B?5NT>!x4vwS9;DJe?4IV&dJ|LEk zOuljhnSb2GfOyDgXJai|>Z-7`x*Wa|7Xh(P(p~IeEXGw0H-jPkap@w?4@3}%sQkJt ziQw2+dNH#0@)_c}$K(vL^3hRWgI6DIM@@y7p+zV%fj}sTbN&c{a-g}on!B)QT_USZ zRpl_XN<7q1imRh>oS}F7#}b%G8k|)Nj5$*+vww7AlO=5HY=K=Cu>05FaPmqYE)Nc3 zbYcR*XcVg(8}ZG~9TxRPK(ToQQ$#qH#F68FW92+CR z-hYFr@Rs7~wX5N;R}4>9uW6g4YJ#3%du5lg0~fU#Tw)RvWT zmdrV1^bf~yq&JBBmniWSi;DnaHdZX~VK^M7#1`T-Pk&Dh zEaV%id<0&ftvEncDM`{?+n;|1FKyXO@9RjVH2ifff@3ts;~MT;SR~3Ay=?VOzH;;i z{zEj8gwtl5#-PsGsrGm{{j<3&L}_Bv#`VNbC79x(Nezd4g18Wf6Z;}hE4i`|r{@h; z9%{?nxI8e(GqqK-vf-@~AjXcz>3^J)%Mz&sD$6~Tj||FRDeOHnLSSMXh$zg`cv zbvt;CvQgeCA=faQ8tVcWFq8L9czEejVp5_SrOpZ{sU{%t22jQRv!fWAPzj7Uw_OJ_ zTJCa?D|Ec@=z45yZNU)vKOBz}TN(%KvfI(Nq@L12vZ$MoW|hsO=}CkWI)8rX8pAMw zvPr_+w?Pb0nbXdz_doqt>9-RPHZ@tLL9m(#_DqtPDdaAm!AXM*jmAP;SE+2o@niSg zz!Xf34r;vF#IJw52k#yHi5renHfD@OX|Ue~!B8|Z7w+8s6+WZd=d#&JKQSEY8G(O1 zH778646#WEsfP*0llW-c7JqnLPF}GcHaXj(WJGRaN?$3a8#2ZobCpO7J9=f1b`?>$ z6#3S6u6C;M7Y9f2#=avI`d(_r95{J(gd)#IE0!q*C~zw5Ec0g>2v(yc!78{cWqh!8 z8wYs)+D#n3;3sCp;x#4PtqBDhG=A`j$D(l(bJTK;nQb{UEJ(Dwwtx1KSumL{z)b6h z^;7J9Srlh%^3%4BJU}kHEn-*Xk*IFe%A!Wnh{JE4-2B} zd7`Fp*W2ss_OP~7u=>lq!5Crp1X1LA%M2D-){v}o`g)-`Cg-C2tb3<-qMeP44;0kU zi|bZ>e0?mm=F;HsCT%+v!MQYGx3CqP?765@RG(Y5a%bzJn!bV`8`u#}B&GeQdtUDH z4{Rb$)T9M>TR+DTmK2q!?kAQvf4GuQQo-I#jH_xaxKJG2oa2FLg7U>HF#97 z1D?X4H7JVAVSlXT+fCDes;K$TDhdXM;E)011GxB8>S{Nizt8w}uM8CxTTo zo`kL$&~+1fmLb;_WHKXI*Z2yvL4l#^FljS16IxcolBrvu8a}9|4{Pe5g{CoOIM!Iz z(x#uj0@OSVPKE@Ks%NQmF0*T@YDU0YiI8_1)-*l?zkjy`hc3K|)wev2P*EkOm#)CF z+ATPJc|R6R-H5i>R|t73P+NKj7F6F4%}jA3oCL?RMIl3`<`E!yVC4642HF%|&mfad zBAFV(jPg}nYJN0??_%UVI3N2CWxfW)2G62*_yQey(bD}1!v0w}(!LvYWh>!Ti&0g) z2)|x>4}V!LgEYs=q*HmC)>GExofw=92}s;l_YgKLUT5`<1RBwq{f)K~I%M=g zRE6dbu_;;M@*@xIj3(|T5$GYA@$XA8gIr zg_2s+Q!vadeBLr^v_l;`(AN7IR8>kT@qeJ8e#%;OB!0k&?tM5L`wY!ZZ=lpy$D>3; zk)B3Y&yJ5LpLGQ!K?64O35SVvBrX`Vah$Yy?^F0oa_At$2<2}Hj_o)`QEQFC)~{Fvfy%n5kv(6 zNyrKTGMOs_nQm)pU4uvQ^QB!3TM;xPgGjImtLvXfGTVp49Xm0Uxy%@Q*msnOX#60i zv8eMaB^D!2P_BTapFD7q_#o1K1HLS$-H#xRs?+!oR011`E`*?-$O7m;R(?2SJ|ghtSH^Y6_CBc+!-2m z78`2CoJcc1Y}sT1kd-t6p??nFc1AhOY`Oxn*>MA;Dqb9jZb#?95mbieaanK0(e6Dw z8eE4O@6oo%f_D+uq_+DBAg3CJj=tnMhR2WIk#kUZT$K81EOvyUYt;gH3NQPyVao$W zv~w#qSo@Ajf=@CzmsW3q&W+Ma9f{~QsG?ZsjNQ}bU|h(gLpC0dCx6@8+EN7N%Am(w zhkf@3%lO{I750J_q zE~+R9Az%^`LPGrmKM+#ckQma$1nV}$Rxwpnv{2eoSeGnKlYge6PMkVTe2Fi|J~!U? zJ9grvvEvh=rjdEfVWKSwf66A$v?zyp3f@CwM)ZqDabOwDI@jND0V zqRTo7xMz5yg=jgXds`YOb~Fbg4oR}7z+1yNpFVSA@_X@I{&CGP>ekJ|4o6~pQ^UK5 z`?tNcr@iIF<$w33l6X&j6^toL1(tU(=jpQVGMt<<|{R3MX1F4EZ{O8eIUy~u#g9e!Q(aBiPsantZ ziRkAm#=!J^)_G$#eo!XZn1*p*WgD|7?6uh3$LQ_kihl|ebUjc|wID~liSm@Qp2bc= z3Ce6#@mqvD+H_&C0*2wJr~qTlF!aU2=5iGX?|&kV+7$qJW9w z10~_j3V%Xj;TfG_C!lA&^J1I?B*_w3EN)t3&Em5{EV|*OlPazFyb|_HAI#$ORuCK2 zsf2i-WO}oxh-CSMFEoOfN)yqtsCT>23|4Af8n)n^7>Cm`5y?g`#Rg8K+Ycet)upmi`)+^#vYyd7b208Uo9L7*^3J znM_1N@pD1b#KfB#{pf9LMqhgf+gpNY^wz=eaSKb*%ff2W0OejRSy`lLy1|~y7F0|p zGq^A|iYt*>OeIxL<&a4ci@ccvI#TH`8P|ll3WSOZNan&9G^v5Uwh*4(xgEPZTG3eV zA%AN*%X~}%ar!0eC~BeR6v^J%(HeqJ-iWS{iC9|4(CsWnXL3j?y0AVMRY+2~fUB@k zvk0A{U@Saa{n#h=qou(w?&tD(MDNUE^mYu9xj94=3CyHYc%-uvNA?d8%=A^mz7!J- zEmbFrlQKPFAG%t7G?#+wq{N4}bBLx2bbsFDxGU z=`t>ij$wRe2JuXWCf9`^imH+_aU3}?uo$^D9`$u~7`i@=e-Do0BfI<1)7gQ6tpPmR z6~a`afPY0&7>Q*un^mD1t9hVI51k$kQji|lz7aFYB))p`WeiSEqR!=liy-8ZWq-J3 zYYHb>FhGK=g~57UGKNOR@$-|fVe8fo{Nl&Qp;FA9diN~)ySL)8{vCLtGmOzW6{)=J zsIen6h3g&)hp@S&5wD&9JBFiC3R>@qPjldg{C-lzNsH^Y6yW$tXLE3|0VFHn`TEs2 zPD7;(^`+-NjXix`dgXOQre|tv>RAXE1x|ms1*!RY3`Qmw;Ih); zq=nmqLEEH*)1#`XNRk4g_?2u#AC!DSeAf{0VgKHKy!8EVU|UDHwiw`)7=NMy)wQ7s z!&8$~bP~e46}dVo+eRMHZT1nI@A8ELlJgmIw6u_#`TNKA?ZRh2^%QpXcELxfd*9AZ z@|LGabyiV;tL>Ih0~!NfT>jflN}UDxsnV_}1i{Bcf!)^7Aoz-1%AC$-ks-{BicQ&! zGhatrD}H$F%kWUOHwj|dynl*|6A743e{OGQ4IW^j`r4bt3PS{+D)1LpXZ*JjgfzPf z(8TkZc@YDQ_ruRVi6Euy5~(lDM;NGw>Q6APV^X$rw>u|Cgb6nh7b7fn|w0TeKk*6=1-o`sif?!~UC z01H{~mPOO@%YXOI;L6PjeCN<-5N>L;jq^pLIEWf21Y`AiJXSwV!Y3)~yiM6AnbT^9 zO-)?LL&EFCMt^_t5`J^;JVvIYl!u*b5}xVzKBM`F~#w_wkgx>-EX7O=R?rvMKqqknUQG`7prJ*%L9TAatdb!GBBNc_|ZlDQ1{{FxL5G3v>16trf9jAz6scMU$crzB(C0JX;WB>`}ieRD!pC zI6F#3dMviti^Pt9CE@*>@=dDc?@RWROB=*xo+*Epm10AzX8py|DV6$lt)c=Rmox2> zowL-Bc1R1NnAV<-RC|z_YlCz3?a{>nlNGa2IDZ&0x>`f0+1i%SMUUA$r5a9K^T8U! zRsW&zhCfwJqlX{v|C!q*$C&s@#eK{5JxKAs5sIhwe#YZ1L(b>`zU-ft5Q`Og{P|9^0MHK0_ue5La$BvqW(E{R@m;+b z+04~`K@~=KAlzM05bd(Nnm)?dxa?uEJXv zeu+q80Dqrd@f`f#Ip`ZXfIAz$i21em;CTN_=xEu3VAVXlcIsQuGdfb46xxDaSk?R` zH2PP;NRz%=?4~pTga_dz#}k`EC}jbv!cw~BHsU&lZlE=|p3FXv_J;eB)>By1vJIEU zj-b8%el*o|VkG)LqNx#TG>Jvj^jIte!!+RY)PJLY@)%lY-vfVDGlHHLY+U$V^iLdv zrg-Q+#?(5pRz7B(*J9e@sgV7wrlqlyV{Kn>8(4v2;-jwVy`N*NVyb04`0ujrO_sVN?6}QB&QD z4GSJe%j~t7rPZQi-XruqkF`oeU>Uj=euKg#v9@g+*0gTHJN>UCC)o`?7zD@J3ChBdeQ!oN8-bK z)HDs<-97KETX)x2xXJ)=m{^cXOT|Ert2__P^~`+Z&V#E9S;5N`C++P3qk^?v1rVm~ zjBq;ys6=tD0*LR676fk>l#4%C0c@r#(S$vBrrWXt+)4|uIHPyU|>La6h%92y4IPufI$9>Xu!@y z`TaNgtg&41@PwMwBdmSm7)xAWDStg10dJ$le#VeeKMN{LP+@#9)=Dy}s; zItmd)fR<7PtqBfRa1}tbFQyiv?qISgtA=i5gaug^9(5La2LFf?gTH4Ln}4k+ErF;= z-IQ`Bh0yq$6zokLP=AUI^S+6dO%L-+9m!-89*>7Y@(fexVMT0Y#VqQ+u?`Qld2!+h zqUjMX>VbzxMA73u+GgKvc?r?JS(VpwP!0HUiC7TuULkc_CJBKkqFd8gJbY!X=N|2>}SVTgb;KG z8CTHJxE0O8PV71L7+pwiVw}GVjqS6>G`g99Zl)=$51*L-G}qEGnSbbqHaCQ79+E=u zUXCOZ35jAMRz%R%0(P!0FMv=sk>Nr8%+OzY^c-M9@+ zfz=G`qj2+%Zca?2GF_~Ag8Z{+AH9ziZejL@FI=nNq3nz#ELXAuA;T*>;hBqKa81dvd z<6{SYg-4wiWq)s33zYnF+JI;-;N=Ylg%+L3uVj~+sx~~d^k>|VJ=ov3eJauU2EUa}8?jjAVjIdWLN~x|EkQziRAeJZ(CKl9w41uafUTzJe$=`uZi++SY2K7JA ze8&>W!#h=xt|D?2FrFI2zR-_dmv$9EzO;Scl}c_fpno-CaqR=VUaUvk>@F_89b@tH zs8R!*QKY;INJ<2_U+K6Ca3e9Gsl2{qY0%a7J?uICWgHuLfj+MB=GkAN1&ifT#2u}B z+2S#~$5jA(Qn^;H%CCmIae4AE-Dsng|Hl*Ov!z72k3ZnJs{pp|+pW`DDueC#mEWOf z=ucJ!dVgwUH@>j^1>TL0u`W8w;Jx`gA+b`%0Pb1H4q!VDoLX66B>p}bl~W&?H8pNf zf56)2Czv7W0=b~Qsa8^~W179L%2Mj#vRQCqI=|0g@wJLYT$WSW0u+`LdvR`TFYo?W zayL$LjI=%o=2*#5$-d=&T?LTKRr`!ux`mZK+kfjHWDJu_CL5173+G1viO%M)LDgs( zNkBJ&R^GCHEN-WinlC}A7?9kRIDY*2SZ{CdB=-Xmlu3c=bp$!2FUGt5ujP&Eh%~%T zAMQdgEh5EUr9e)lIFdhgjYQNO<97+7V?K4FDt+}iT+enfv5qJ;aLMZpj@?R-eY*9u||RB?bS+IKo}Kc5yWnb blIs5eNSY+j744LC00000NkvXXu0mjf#T4BU diff --git a/res/drawable/basic_rectangle.xml b/res/drawable/basic_rectangle.xml index 63a7114..abb8504 100644 --- a/res/drawable/basic_rectangle.xml +++ b/res/drawable/basic_rectangle.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/res/drawable/bike.png b/res/drawable/bike.png new file mode 100644 index 0000000000000000000000000000000000000000..3730150e1349cfe6971fe63b5ee47bee0ebf238e GIT binary patch literal 1008 zcmVHq)$8FWQhbW?9;ba!ELWdL_~cP?peYja~^ zaAhuUa%Y?FJQ@H118qq}K~zYIrPf=BmQ@r6;AciN>4bq; zfUJn=B9RWDNk!p>RHRU;6?74m;guvtk%D0-i%Ly8c!I)1lzWR>1a(n(_`BG9;%{nZ ze&~gL^X+%7{eJ6P>)l^lqtVb8a?S&=1oLq=eu;=-eFnCO{w?zE!lPBlVf@sckaKRs z8@Q<3*0zXvq_^a4EmmR|_C~~QEpRVUD)ul|U~5FI{a+$-&Qq`rFXFR46&K9Iq=*>a z3b_>#Pvh|x4{t^T<0E2kU&QtnlHH6`xD%(>H2|k6J=Gum&>j(OSb&o_g2k<DW`Rn5HyE&d2V$Zit9KYSKGu!V540@74-Ut0ji15plTk=U@XS;T@$p zr(zkVU~EJ*Dz^>maXl_?S2}ng?&%UxF$Y^B;#frNP|RmU4V;BDu_@;~sPa3p73W|$ zIwRr`o~v&^rz>$4Grv}TVLPtG=MizRskH5wUDbABV-31CBKG6PTJ{Y&=i!*EH1BNu zru2h|_!^tBuql^_IHH)}741r+?etHKQ09MqQ_!#VO-D8*pQ}vLcEvk7aJ$kAi*nA3 zbIyx!6f<+q6S|$V2jlwVM`aY7RUXJWkE{nbV~AqmUA&KT&NJ{BE>?_f2+qL0-C}nt zm)o~Z&qiZkTS{p)W@1!C9M=PK&O?>CUlb85d*R)WmoPCRzUhT`7WU)qcD%04_0paK zDqc~(^}0TIYw$Z(*8h;6@GJ)5WsOEdN@-O}>10Z2SxRYOqtVc{Qc8nUN^4U}jg(Sn z^IlIYr8GCCbRwm+F{RYeZSUNa((0OTNu$vyj#=$`IUZDgT0T)M_AH+q0000nu~K~zYI&6ZtAQ(+j#fBR4frj~7UeOa?aJ!BVt7D6K8wUAxp z2iPZxBPKzwD+cCl2IH{kgg8kmW(s;;67UE}h%ZjKL;-@YUr4ps}NahNsT~usR%^yL*q$zCHljdwUt2nxZm4KPET`l(-4dMw>A2@zC|z zPKH{|%U;W-f9yayhg3=cb}JN=3fahIfi0e?)^J3lre|a{WNTpDs5EDaoXIeJok~@vW>N_5MJ*nn#ZqEG-ZK0SkS*G}Avi+ERk zXjDo*d>V)bu)%3EUxkoP5)EJ+)CH6}O=ceibrKOx0ylt-6$Fo4d9mcE_}#JG1WN1M zfQa}6<0VybQ8qBRep=%+nOlS7F~21LP|cxmuzdhWfD2-Q?EvT{P})VY;4cpB_BS^1 RsnP%d002ovPDHLkV1oPobb9~* literal 0 HcmV?d00001 diff --git a/res/layout/add_favorite.xml b/res/layout/add_favorite.xml index c4766af..641154c 100644 --- a/res/layout/add_favorite.xml +++ b/res/layout/add_favorite.xml @@ -5,7 +5,7 @@ + android:text="@string/add_route" android:paddingBottom="10dp" /> - + + - - + + + + \ No newline at end of file diff --git a/res/layout/simple_spinner_item.xml b/res/layout/simple_spinner_item.xml index feb52ff..d20985a 100644 --- a/res/layout/simple_spinner_item.xml +++ b/res/layout/simple_spinner_item.xml @@ -3,6 +3,6 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingTop="15dip" android:paddingBottom="15dip" android:paddingLeft="5dip" android:paddingRight="5dip" android:id="@android:id/text1" - android:textColor="#cccccc" android:ellipsize="marquee" + android:ellipsize="marquee" android:textColor="@color/black" android:singleLine="true"> diff --git a/res/menu/favorite_context_menu.xml b/res/menu/route_context_menu.xml similarity index 100% rename from res/menu/favorite_context_menu.xml rename to res/menu/route_context_menu.xml diff --git a/res/menu/route_menu.xml b/res/menu/route_menu.xml new file mode 100644 index 0000000..9e77838 --- /dev/null +++ b/res/menu/route_menu.xml @@ -0,0 +1,5 @@ + + + + diff --git a/res/menu/favorites_menu.xml b/res/menu/routes_list_menu.xml similarity index 64% rename from res/menu/favorites_menu.xml rename to res/menu/routes_list_menu.xml index b233735..c9d1c67 100644 --- a/res/menu/favorites_menu.xml +++ b/res/menu/routes_list_menu.xml @@ -1,5 +1,5 @@ - diff --git a/res/values/strings.xml b/res/values/strings.xml index 608bde4..8b9b596 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2,23 +2,24 @@ Bart Catcher Favorite Routes - Press the menu button and select "Add - favorite" to - add a route - Add favorite - Add a favorite route + Press the menu button and select \"Add route\" to add + a route + Add a route Origin Destination Save - The origin and destination stations must be different + The origin and destination stations must be + different You must select a destination station You must select an origin station - Please wait while real time arrival data is loaded... - No arrival data is currently available for this route + Please wait while real time arrival data is + loaded... + No arrival data is currently available for this + route View View arrivals Delete Yes Cancel - + View details on BART site diff --git a/res/values/styles.xml b/res/values/styles.xml index ceb242f..22dd137 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -21,8 +21,18 @@ + + + + + diff --git a/src/com/dougkeen/bart/AddFavoriteActivity.java b/src/com/dougkeen/bart/AddRouteActivity.java similarity index 87% rename from src/com/dougkeen/bart/AddFavoriteActivity.java rename to src/com/dougkeen/bart/AddRouteActivity.java index b7a5e54..d813dba 100644 --- a/src/com/dougkeen/bart/AddFavoriteActivity.java +++ b/src/com/dougkeen/bart/AddRouteActivity.java @@ -1,6 +1,6 @@ package com.dougkeen.bart; -import com.dougkeen.bart.data.FavoritesColumns; +import com.dougkeen.bart.data.RoutesColumns; import android.app.Activity; import android.content.ContentValues; @@ -14,7 +14,7 @@ import android.widget.Spinner; import android.widget.SpinnerAdapter; import android.widget.Toast; -public class AddFavoriteActivity extends Activity { +public class AddRouteActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { @@ -80,8 +80,8 @@ public class AddFavoriteActivity extends Activity { } ContentValues values = new ContentValues(); - values.put(FavoritesColumns.FROM_STATION.string, origin.abbreviation); - values.put(FavoritesColumns.TO_STATION.string, destination.abbreviation); + values.put(RoutesColumns.FROM_STATION.string, origin.abbreviation); + values.put(RoutesColumns.TO_STATION.string, destination.abbreviation); Uri newUri = getContentResolver().insert( Constants.FAVORITE_CONTENT_URI, values); diff --git a/src/com/dougkeen/bart/ArrivalArrayAdapter.java b/src/com/dougkeen/bart/ArrivalArrayAdapter.java new file mode 100644 index 0000000..fdfa095 --- /dev/null +++ b/src/com/dougkeen/bart/ArrivalArrayAdapter.java @@ -0,0 +1,90 @@ +package com.dougkeen.bart; + +import java.util.List; + +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.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.dougkeen.bart.data.Arrival; + +public class ArrivalArrayAdapter extends ArrayAdapter { + + public ArrivalArrayAdapter(Context context, int textViewResourceId, + Arrival[] objects) { + super(context, textViewResourceId, objects); + } + + public ArrivalArrayAdapter(Context context, int resource, + int textViewResourceId, Arrival[] objects) { + super(context, resource, textViewResourceId, objects); + } + + public ArrivalArrayAdapter(Context context, int resource, + int textViewResourceId, List objects) { + super(context, resource, textViewResourceId, objects); + } + + public ArrivalArrayAdapter(Context context, int resource, + int textViewResourceId) { + super(context, resource, textViewResourceId); + } + + public ArrivalArrayAdapter(Context context, int textViewResourceId, + List objects) { + super(context, textViewResourceId, objects); + } + + public ArrivalArrayAdapter(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.arrival_listing, parent, false); + } + + Arrival arrival = getItem(position); + ((TextView) view.findViewById(R.id.destinationText)).setText(arrival + .getDestination().toString()); + ((TextView) view.findViewById(R.id.trainLengthText)).setText(arrival + .getTrainLengthText()); + ImageView colorBar = (ImageView) view + .findViewById(R.id.destinationColorBar); + ((GradientDrawable) colorBar.getDrawable()).setColor(Color + .parseColor(arrival.getDestinationColor())); + ((TextView) view.findViewById(R.id.countdown)).setText(arrival + .getCountdownText()); + ((TextView) view.findViewById(R.id.uncertainty)).setText(arrival + .getUncertaintyText()); + if (arrival.isBikeAllowed()) { + ((ImageView) view.findViewById(R.id.bikeIcon)) + .setVisibility(View.VISIBLE); + } else { + ((ImageView) view.findViewById(R.id.bikeIcon)) + .setVisibility(View.INVISIBLE); + } + if (arrival.getRequiresTransfer()) { + ((ImageView) view.findViewById(R.id.xferIcon)) + .setVisibility(View.VISIBLE); + } else { + ((ImageView) view.findViewById(R.id.xferIcon)) + .setVisibility(View.INVISIBLE); + } + + return view; + } + +} diff --git a/src/com/dougkeen/bart/GetRealTimeArrivalsTask.java b/src/com/dougkeen/bart/GetRealTimeArrivalsTask.java index 7cbb075..d4712f1 100644 --- a/src/com/dougkeen/bart/GetRealTimeArrivalsTask.java +++ b/src/com/dougkeen/bart/GetRealTimeArrivalsTask.java @@ -40,7 +40,11 @@ public abstract class GetRealTimeArrivalsTask extends throw new RuntimeException(e); } - return getArrivalsFromNetwork(params, sourceUrl, 0); + if (!isCancelled()) { + return getArrivalsFromNetwork(params, sourceUrl, 0); + } else { + return null; + } } private RealTimeArrivals getArrivalsFromNetwork(Params params, @@ -48,6 +52,9 @@ public abstract class GetRealTimeArrivalsTask extends try { EtdContentHandler handler = new EtdContentHandler(params.origin, params.destination, mRoutes); + if (isCancelled()) { + return null; + } Xml.parse(sourceUrl.openStream(), Xml.findEncodingByName("UTF-8"), handler); final RealTimeArrivals realTimeArrivals = handler diff --git a/src/com/dougkeen/bart/Route.java b/src/com/dougkeen/bart/Route.java index 3ac9c00..8d100f5 100644 --- a/src/com/dougkeen/bart/Route.java +++ b/src/com/dougkeen/bart/Route.java @@ -5,6 +5,7 @@ public class Route { private Station destination; private Line line; private boolean requiresTransfer; + private Station transferStation; private String direction; public Station getOrigin() { @@ -39,6 +40,14 @@ public class Route { this.requiresTransfer = requiresTransfer; } + public Station getTransferStation() { + return transferStation; + } + + public void setTransferStation(Station transferStation) { + this.transferStation = transferStation; + } + public String getDirection() { return direction; } @@ -58,6 +67,8 @@ public class Route { builder.append(line); builder.append(", requiresTransfer="); builder.append(requiresTransfer); + builder.append(", transferStation="); + builder.append(transferStation); builder.append(", direction="); builder.append(direction); builder.append("]"); diff --git a/src/com/dougkeen/bart/FavoritesDashboardActivity.java b/src/com/dougkeen/bart/RoutesListActivity.java similarity index 89% rename from src/com/dougkeen/bart/FavoritesDashboardActivity.java rename to src/com/dougkeen/bart/RoutesListActivity.java index 3a23a02..f8fa9b8 100644 --- a/src/com/dougkeen/bart/FavoritesDashboardActivity.java +++ b/src/com/dougkeen/bart/RoutesListActivity.java @@ -24,9 +24,9 @@ import android.widget.SimpleCursorAdapter.ViewBinder; import android.widget.TextView; import com.dougkeen.bart.data.CursorUtils; -import com.dougkeen.bart.data.FavoritesColumns; +import com.dougkeen.bart.data.RoutesColumns; -public class FavoritesDashboardActivity extends ListActivity { +public class RoutesListActivity extends ListActivity { private static final int DIALOG_DELETE_EVENT = 0; protected Cursor mQuery; @@ -41,22 +41,17 @@ public class FavoritesDashboardActivity extends ListActivity { super.onCreate(savedInstanceState); setContentView(R.layout.main); - ((TextView) findViewById(R.id.listTitle)) - .setText(R.string.favorite_routes); - ((TextView) findViewById(android.R.id.empty)) - .setText(R.string.empty_favorites_list_message); - mQuery = managedQuery(Constants.FAVORITE_CONTENT_URI, new String[] { - FavoritesColumns._ID.string, - FavoritesColumns.FROM_STATION.string, - FavoritesColumns.TO_STATION.string }, null, null, - FavoritesColumns._ID.string); + RoutesColumns._ID.string, + RoutesColumns.FROM_STATION.string, + RoutesColumns.TO_STATION.string }, null, null, + RoutesColumns._ID.string); SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.favorite_listing, mQuery, - new String[] { FavoritesColumns.FROM_STATION.string, - FavoritesColumns.TO_STATION.string }, + new String[] { RoutesColumns.FROM_STATION.string, + RoutesColumns.TO_STATION.string }, new int[] { R.id.originText, R.id.destinationText }); adapter.setViewBinder(new ViewBinder() { @@ -74,10 +69,19 @@ public class FavoritesDashboardActivity extends ListActivity { registerForContextMenu(getListView()); } + @Override + protected void onResume() { + super.onResume(); + ((TextView) findViewById(R.id.listTitle)) + .setText(R.string.favorite_routes); + ((TextView) findViewById(android.R.id.empty)) + .setText(R.string.empty_favorites_list_message); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.favorites_menu, menu); + inflater.inflate(R.menu.routes_list_menu, menu); return true; } @@ -105,15 +109,15 @@ public class FavoritesDashboardActivity extends ListActivity { super.onCreateContextMenu(menu, v, menuInfo); MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.favorite_context_menu, menu); + inflater.inflate(R.menu.route_context_menu, menu); AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo; CursorWrapper item = (CursorWrapper) getListAdapter().getItem( info.position); Station orig = Station.getByAbbreviation(CursorUtils.getString(item, - FavoritesColumns.FROM_STATION)); + RoutesColumns.FROM_STATION)); Station dest = Station.getByAbbreviation(CursorUtils.getString(item, - FavoritesColumns.TO_STATION)); + RoutesColumns.TO_STATION)); mCurrentlySelectedRouteName = orig.name + " - " + dest.name; menu.setHeaderTitle(mCurrentlySelectedRouteName); } diff --git a/src/com/dougkeen/bart/Station.java b/src/com/dougkeen/bart/Station.java index 984928d..fe5120d 100644 --- a/src/com/dougkeen/bart/Station.java +++ b/src/com/dougkeen/bart/Station.java @@ -115,10 +115,11 @@ public enum Station { } public List getRoutesForDestination(Station dest) { - return getRoutesForDestination(dest, false); + return getRoutesForDestination(dest, null); } - public List getRoutesForDestination(Station dest, boolean isTransfer) { + public List getRoutesForDestination(Station dest, + Station transferStation) { if (dest == null) return null; Boolean isNorth = null; @@ -140,7 +141,7 @@ public enum Station { route.setDestination(dest); route.setDirection(isNorth ? "n" : "s"); route.setLine(line); - if (isTransfer || line.requiresTransfer) { + if (transferStation != null || line.requiresTransfer) { route.setTransfer(true); } else { route.setTransfer(false); @@ -149,11 +150,14 @@ public enum Station { } if (isNorth == null) { if (outboundTransferStation != null) { - returnList.addAll(getOutboundTransferStation() - .getRoutesForDestination(dest, true)); + returnList + .addAll(getOutboundTransferStation() + .getRoutesForDestination(dest, + getOutboundTransferStation())); } else { returnList.addAll(getRoutesForDestination(dest - .getInboundTransferStation(), true)); + .getInboundTransferStation(), dest + .getInboundTransferStation())); } } return returnList; diff --git a/src/com/dougkeen/bart/ViewArrivalsActivity.java b/src/com/dougkeen/bart/ViewArrivalsActivity.java index 15c373c..66ec9cf 100644 --- a/src/com/dougkeen/bart/ViewArrivalsActivity.java +++ b/src/com/dougkeen/bart/ViewArrivalsActivity.java @@ -10,18 +10,29 @@ import android.database.Cursor; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; +import android.os.Parcelable; import android.os.PowerManager; +import android.text.format.DateFormat; +import android.util.Log; +import android.util.TimeFormatException; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.widget.ArrayAdapter; import android.widget.TextView; import android.widget.Toast; import com.dougkeen.bart.GetRealTimeArrivalsTask.Params; import com.dougkeen.bart.data.Arrival; -import com.dougkeen.bart.data.FavoritesColumns; +import com.dougkeen.bart.data.RoutesColumns; import com.dougkeen.bart.data.RealTimeArrivals; public class ViewArrivalsActivity extends ListActivity { + private static final String TAG = "BartCatcher"; + + private static final int UNCERTAINTY_THRESHOLD = 17; + private Uri mUri; private Station mOrigin; @@ -44,9 +55,10 @@ public class ViewArrivalsActivity extends ListActivity { private PowerManager.WakeLock mWakeLock; + private boolean mFetchArrivalsOnNextFocus; + @Override protected void onCreate(Bundle savedInstanceState) { - // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.main); @@ -59,8 +71,8 @@ public class ViewArrivalsActivity extends ListActivity { } Cursor cursor = managedQuery(mUri, new String[] { - FavoritesColumns.FROM_STATION.string, - FavoritesColumns.TO_STATION.string }, null, null, null); + RoutesColumns.FROM_STATION.string, + RoutesColumns.TO_STATION.string }, null, null, null); if (!cursor.moveToFirst()) { throw new IllegalStateException("URI not found: " + mUri.toString()); @@ -75,31 +87,69 @@ public class ViewArrivalsActivity extends ListActivity { ((TextView) findViewById(android.R.id.empty)) .setText(R.string.arrival_wait_message); - mArrivalsAdapter = new ArrayAdapter( - this, R.layout.simple_spinner_item); + mArrivalsAdapter = new ArrivalArrayAdapter(this, + R.layout.arrival_listing); + if (savedInstanceState != null + && savedInstanceState.containsKey("arrivals")) { + for (Parcelable arrival : savedInstanceState + .getParcelableArray("arrivals")) { + mArrivalsAdapter.add((Arrival) arrival); + } + } setListAdapter(mArrivalsAdapter); - fetchLatestArrivals(); + mFetchArrivalsOnNextFocus = true; + } + + @Override + protected void onDestroy() { + if (mGetArrivalsTask != null) { + mGetArrivalsTask.cancel(true); + } + super.onDestroy(); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + Arrival[] arrivals = new Arrival[mArrivalsAdapter.getCount()]; + for (int i = mArrivalsAdapter.getCount() - 1; i >= 0; i--) { + arrivals[i] = mArrivalsAdapter.getItem(i); + } + outState.putParcelableArray("arrivals", arrivals); } @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { + if (mFetchArrivalsOnNextFocus) { + fetchLatestArrivals(); + mFetchArrivalsOnNextFocus = false; + } PowerManager powerManaer = (PowerManager) getSystemService(Context.POWER_SERVICE); mWakeLock = powerManaer.newWakeLock( PowerManager.SCREEN_DIM_WAKE_LOCK, "ViewArrivalsActivity"); mWakeLock.acquire(); + if (mArrivalsAdapter != null && !mArrivalsAdapter.isEmpty()) { + mIsAutoUpdating = true; + } + runAutoUpdate(); } else if (mWakeLock != null) { mWakeLock.release(); } } private void fetchLatestArrivals() { + if (!hasWindowFocus()) + return; + mGetArrivalsTask = new GetRealTimeArrivalsTask() { @Override public void onResult(RealTimeArrivals result) { + Log.i(TAG, "Processing data from server"); processLatestArrivals(result); + Log.i(TAG, "Done processing data from server"); } @Override @@ -108,6 +158,7 @@ public class ViewArrivalsActivity extends ListActivity { Toast.LENGTH_SHORT).show(); } }; + Log.i(TAG, "Fetching data from server"); mGetArrivalsTask.execute(new GetRealTimeArrivalsTask.Params(mOrigin, mDestination)); } @@ -119,6 +170,7 @@ public class ViewArrivalsActivity extends ListActivity { return; } + boolean needsBetterAccuracy = false; Arrival firstArrival = null; final List arrivals = result.getArrivals(); if (mArrivalsAdapter.getCount() > 0) { @@ -148,6 +200,9 @@ public class ViewArrivalsActivity extends ListActivity { if (firstArrival == null) { firstArrival = existingArrival; } + if (existingArrival.getUncertaintySeconds() > UNCERTAINTY_THRESHOLD) { + needsBetterAccuracy = true; + } } } else { for (Arrival arrival : arrivals) { @@ -156,12 +211,13 @@ public class ViewArrivalsActivity extends ListActivity { } mArrivalsAdapter.add(arrival); } + needsBetterAccuracy = true; } mArrivalsAdapter.notifyDataSetChanged(); if (hasWindowFocus() && firstArrival != null) { - if (firstArrival.getUncertaintySeconds() > 17 - || firstArrival.getMinutes() == 0) { + if (needsBetterAccuracy + || firstArrival.hasArrived()) { // Get more data in 20s mListTitleView.postDelayed(new Runnable() { @Override @@ -169,27 +225,29 @@ public class ViewArrivalsActivity extends ListActivity { fetchLatestArrivals(); } }, 20000); + Log.i(TAG, "Scheduled another data fetch in 20s"); } else { // Get more when next train arrives + final int interval = firstArrival.getMinSecondsLeft() * 1000; mListTitleView.postDelayed(new Runnable() { @Override public void run() { fetchLatestArrivals(); } - }, firstArrival.getMinSecondsLeft() * 1000); + }, interval); + Log.i(TAG, "Scheduled another data fetch in " + interval / 1000 + + "s"); } if (!mIsAutoUpdating) { mIsAutoUpdating = true; - runAutoUpdate(); } } else { mIsAutoUpdating = false; } - } private void runAutoUpdate() { - if (mIsAutoUpdating) { + if (mIsAutoUpdating && mArrivalsAdapter != null) { mArrivalsAdapter.notifyDataSetChanged(); } if (hasWindowFocus()) { @@ -198,4 +256,30 @@ public class ViewArrivalsActivity extends ListActivity { mIsAutoUpdating = false; } } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.route_menu, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int itemId = item.getItemId(); + if (itemId == R.id.view_on_bart_site_button) { + startActivity(new Intent( + Intent.ACTION_VIEW, + Uri.parse("http://m.bart.gov/schedules/qp_results.aspx?type=departure&date=today&time=" + + DateFormat.format("h:mmaa", + System.currentTimeMillis()) + "&orig=" + + mOrigin.abbreviation + + "&dest=" + + mDestination.abbreviation))); + mFetchArrivalsOnNextFocus = true; + return true; + } else { + return super.onOptionsItemSelected(item); + } + } } diff --git a/src/com/dougkeen/bart/data/Arrival.java b/src/com/dougkeen/bart/data/Arrival.java index 291e21c..0ba3cc4 100644 --- a/src/com/dougkeen/bart/data/Arrival.java +++ b/src/com/dougkeen/bart/data/Arrival.java @@ -1,8 +1,11 @@ package com.dougkeen.bart.data; +import android.os.Parcel; +import android.os.Parcelable; + import com.dougkeen.bart.Station; -public class Arrival implements Comparable { +public class Arrival implements Parcelable, Comparable { public Arrival() { super(); } @@ -20,6 +23,10 @@ public class Arrival implements Comparable { this.minutes = minutes; } + public Arrival(Parcel in) { + readFromParcel(in); + } + private Station destination; private String destinationColor; private String platform; @@ -93,6 +100,10 @@ public class Arrival implements Comparable { this.trainLength = trainLength; } + public String getTrainLengthText() { + return trainLength + " car train"; + } + public boolean getRequiresTransfer() { return requiresTransfer; } @@ -142,14 +153,24 @@ public class Arrival implements Comparable { .currentTimeMillis()) / 1000); } + public boolean hasArrived() { + return getMinutes() == 0 || getMeanSecondsLeft() < 0; + } + public void calculateEstimates(long originalEstimateTime) { setMinEstimate(originalEstimateTime + (getMinutes() * 60 * 1000)); setMaxEstimate(getMinEstimate() + (59 * 1000)); } public void mergeEstimate(Arrival arrival) { - setMinEstimate(Math.max(getMinEstimate(), arrival.getMinEstimate())); - setMaxEstimate(Math.min(getMaxEstimate(), arrival.getMaxEstimate())); + final long newMin = Math + .max(getMinEstimate(), arrival.getMinEstimate()); + final long newMax = Math + .min(getMaxEstimate(), arrival.getMaxEstimate()); + if (newMax > newMin) { // We can never have 0 or negative uncertainty + setMinEstimate(newMin); + setMaxEstimate(newMax); + } } @Override @@ -193,27 +214,79 @@ public class Arrival implements Comparable { return delta > -60000 && delta < 60000; } - @Override - public String toString() { + public String getCountdownText() { StringBuilder builder = new StringBuilder(); - builder.append(destination); - if(requiresTransfer) { - builder.append(" (w/ xfer)"); - } - builder.append(", "); - builder.append(trainLength); int secondsLeft = getMeanSecondsLeft(); - if (getMinutes() == 0 || secondsLeft < 0) { - builder.append(" car train has arrived"); + if (hasArrived()) { + builder.append("Arrived"); } else { - builder.append(" car train in "); builder.append(secondsLeft / 60); builder.append("m, "); builder.append(secondsLeft % 60); - builder.append("s, ±"); - builder.append(getUncertaintySeconds()); builder.append("s"); } return builder.toString(); } -} + + public String getUncertaintyText() { + if (hasArrived()) { + return ""; + } else { + return "(±" + getUncertaintySeconds() + "s)"; + } + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append(destination); + if (requiresTransfer) { + builder.append(" (w/ xfer)"); + } + builder.append(", "); + builder.append(getCountdownText()); + return builder.toString(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(destination.abbreviation); + dest.writeString(destinationColor); + dest.writeString(platform); + dest.writeString(direction); + dest.writeByte((byte) (bikeAllowed ? 1 : 0)); + dest.writeInt(trainLength); + dest.writeByte((byte) (requiresTransfer ? 1 : 0)); + dest.writeInt(minutes); + dest.writeLong(minEstimate); + dest.writeLong(maxEstimate); + } + + private void readFromParcel(Parcel in) { + destination = Station.getByAbbreviation(in.readString()); + destinationColor = in.readString(); + platform = in.readString(); + direction = in.readString(); + bikeAllowed = in.readByte() != 0; + trainLength = in.readInt(); + requiresTransfer = in.readByte() != 0; + minutes = in.readInt(); + minEstimate = in.readLong(); + maxEstimate = in.readLong(); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public Arrival createFromParcel(Parcel in) { + return new Arrival(in); + } + + public Arrival[] newArray(int size) { + return new Arrival[size]; + } + }; +} \ No newline at end of file diff --git a/src/com/dougkeen/bart/data/BartContentProvider.java b/src/com/dougkeen/bart/data/BartContentProvider.java index fb43be6..b3307c3 100644 --- a/src/com/dougkeen/bart/data/BartContentProvider.java +++ b/src/com/dougkeen/bart/data/BartContentProvider.java @@ -26,7 +26,7 @@ public class BartContentProvider extends ContentProvider { /** * The default sort order for events */ - private static final String DEFAULT_SORT_ORDER = FavoritesColumns.FROM_STATION.string + private static final String DEFAULT_SORT_ORDER = RoutesColumns.FROM_STATION.string + " DESC"; static { @@ -35,12 +35,12 @@ public class BartContentProvider extends ContentProvider { sUriMatcher.addURI(Constants.AUTHORITY, "favorites/#", FAVORITE_ID); sFavoritesProjectionMap = new HashMap(); - sFavoritesProjectionMap.put(FavoritesColumns._ID.string, - FavoritesColumns._ID.string); - sFavoritesProjectionMap.put(FavoritesColumns.FROM_STATION.string, - FavoritesColumns.FROM_STATION.string); - sFavoritesProjectionMap.put(FavoritesColumns.TO_STATION.string, - FavoritesColumns.TO_STATION.string); + sFavoritesProjectionMap.put(RoutesColumns._ID.string, + RoutesColumns._ID.string); + sFavoritesProjectionMap.put(RoutesColumns.FROM_STATION.string, + RoutesColumns.FROM_STATION.string); + sFavoritesProjectionMap.put(RoutesColumns.TO_STATION.string, + RoutesColumns.TO_STATION.string); } private DatabaseHelper mDatabaseHelper; @@ -81,7 +81,7 @@ public class BartContentProvider extends ContentProvider { } else if (match == FAVORITE_ID) { qb.setTables(DatabaseHelper.FAVORITES_TABLE_NAME); qb.setProjectionMap(sFavoritesProjectionMap); - qb.appendWhere(FavoritesColumns._ID + " = " + qb.appendWhere(RoutesColumns._ID + " = " + uri.getPathSegments().get(1)); } else { throw new IllegalArgumentException("Unknown URI " + uri); @@ -121,12 +121,12 @@ public class BartContentProvider extends ContentProvider { long rowId = -1; Cursor cursor = db .query(DatabaseHelper.FAVORITES_TABLE_NAME, - new String[] { FavoritesColumns._ID.string }, - FavoritesColumns.FROM_STATION + "=? AND " - + FavoritesColumns.TO_STATION + "=?", + new String[] { RoutesColumns._ID.string }, + RoutesColumns.FROM_STATION + "=? AND " + + RoutesColumns.TO_STATION + "=?", new String[] { - values.getAsString(FavoritesColumns.FROM_STATION.string), - values.getAsString(FavoritesColumns.TO_STATION.string) }, + values.getAsString(RoutesColumns.FROM_STATION.string), + values.getAsString(RoutesColumns.TO_STATION.string) }, null, null, null); @@ -139,7 +139,7 @@ public class BartContentProvider extends ContentProvider { } if (rowId < 0) { rowId = db.insert(DatabaseHelper.FAVORITES_TABLE_NAME, - FavoritesColumns.FROM_STATION.string, values); + RoutesColumns.FROM_STATION.string, values); } if (rowId > 0) { Uri eventUri = ContentUris.withAppendedId( @@ -174,7 +174,7 @@ public class BartContentProvider extends ContentProvider { } else if (match == FAVORITE_ID) { String favoriteId = uri.getPathSegments().get(1); count = db.delete(DatabaseHelper.FAVORITES_TABLE_NAME, - FavoritesColumns._ID + " = " + RoutesColumns._ID + " = " + favoriteId + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs); diff --git a/src/com/dougkeen/bart/data/CursorUtils.java b/src/com/dougkeen/bart/data/CursorUtils.java index 5288f72..868ab1d 100644 --- a/src/com/dougkeen/bart/data/CursorUtils.java +++ b/src/com/dougkeen/bart/data/CursorUtils.java @@ -13,7 +13,7 @@ public final class CursorUtils { } } - public static final String getString(Cursor cursor, FavoritesColumns column) { + public static final String getString(Cursor cursor, RoutesColumns column) { return cursor.getString(cursor.getColumnIndex(column.string)); } diff --git a/src/com/dougkeen/bart/data/DatabaseHelper.java b/src/com/dougkeen/bart/data/DatabaseHelper.java index a9decb5..9c53e4d 100644 --- a/src/com/dougkeen/bart/data/DatabaseHelper.java +++ b/src/com/dougkeen/bart/data/DatabaseHelper.java @@ -18,9 +18,9 @@ public class DatabaseHelper extends SQLiteOpenHelper { @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE " + FAVORITES_TABLE_NAME + " (" + - FavoritesColumns._ID.getColumnDef() + " PRIMARY KEY, " + - FavoritesColumns.FROM_STATION.getColumnDef() + ", " + - FavoritesColumns.TO_STATION.getColumnDef() + ");"); + RoutesColumns._ID.getColumnDef() + " PRIMARY KEY, " + + RoutesColumns.FROM_STATION.getColumnDef() + ", " + + RoutesColumns.TO_STATION.getColumnDef() + ");"); } @Override diff --git a/src/com/dougkeen/bart/data/FavoritesColumns.java b/src/com/dougkeen/bart/data/RoutesColumns.java similarity index 77% rename from src/com/dougkeen/bart/data/FavoritesColumns.java rename to src/com/dougkeen/bart/data/RoutesColumns.java index fc3d53e..435fb59 100644 --- a/src/com/dougkeen/bart/data/FavoritesColumns.java +++ b/src/com/dougkeen/bart/data/RoutesColumns.java @@ -1,12 +1,12 @@ package com.dougkeen.bart.data; -public enum FavoritesColumns { +public enum RoutesColumns { _ID("_id", "INTEGER"), FROM_STATION("FROM_STATION", "TEXT"), TO_STATION("TO_STATION", "TEXT"); // This class cannot be instantiated - private FavoritesColumns(String string, String type) { + private RoutesColumns(String string, String type) { this.string = string; this.sqliteType = type; } diff --git a/xfer.svg b/xfer.svg new file mode 100644 index 0000000..60929ef --- /dev/null +++ b/xfer.svg @@ -0,0 +1,109 @@ + + + + + + + + + + + image/svg+xml + + + + + + + + XFER + +