From 57d8fb2debc7551ac912a77fbb23a35e77c7f055 Mon Sep 17 00:00:00 2001 From: Quddus Chong Date: Mon, 19 Oct 2015 15:56:01 -0700 Subject: [PATCH] docs: Removing obsolete Notepad tutorial. bug: 18940278, 1426263, 1426251 Change-Id: Id47439071454f333129465d88eee5ab45fecce5d --- .../notepad/codelab/NotepadCodeLab.zip | Bin 93415 -> 0 bytes docs/html/training/notepad/index.jd | 136 ---- docs/html/training/notepad/notepad-ex1.jd | 583 ---------------- docs/html/training/notepad/notepad-ex2.jd | 645 ------------------ docs/html/training/notepad/notepad-ex3.jd | 367 ---------- .../training/notepad/notepad-extra-credit.jd | 71 -- docs/html/training/notepad/notepad-index.jd | 144 ---- 7 files changed, 1946 deletions(-) delete mode 100644 docs/html/training/notepad/codelab/NotepadCodeLab.zip delete mode 100644 docs/html/training/notepad/index.jd delete mode 100644 docs/html/training/notepad/notepad-ex1.jd delete mode 100644 docs/html/training/notepad/notepad-ex2.jd delete mode 100644 docs/html/training/notepad/notepad-ex3.jd delete mode 100644 docs/html/training/notepad/notepad-extra-credit.jd delete mode 100644 docs/html/training/notepad/notepad-index.jd diff --git a/docs/html/training/notepad/codelab/NotepadCodeLab.zip b/docs/html/training/notepad/codelab/NotepadCodeLab.zip deleted file mode 100644 index cd30f291587a7235be5702a3f5fd481af249eafb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 93415 zcmeFZWpp0Pm9{Nr28)?3W@ct)W|k~wW(JEaW{a7bnVG?2W~R?4nMo!y$w|&ketc`a z)>`#El78G(y}No>b?^IXIZ0p;D1hI7h-Ig_{`AX#e82;s0?61p8h_C@60|ikmeMz% zRaSxo0Nz!^l-m2*lwCmpCN)Bl<^G`p#{X3K4?$eO+K4<^slt;x&O9Im)1Yf+N5RdHV_m?3dKY1km{>hDPSM6VK9jIimU~A1_7sXorsnQs7ISX z2BU-4nNZ__5-2JI8_86o)zVnUY-2{;&{xf|x@hkxoi@Uf%rf)~;CMh4|8AU(ZPu$8CuXJ!i8m!Nb2oICujF^%h1T}Ugo88!dNyHI=T6RH%1E=*&md|IsKr3b zl*C*_G`3XidWG2msUHfBp~MTeR>(Un$Iu#ST<2~N0Ink-(VHnijv&t0nZ(HQuaJyn zuQ&qGSjE@KptFL(l87_}eQ=3)jqXqC- z20p@c=r~}%BN+)!gedS7B`LxwlFw*rn4Jq$jg{z^U89@LcwIzEv`eSEU;FZMY9i~> zxwYyvQ354%VBS5yv`tu<3Usst?Zvumvqp@=NsJY74AUB{3d-&U(s8lqZ{k!ZbeoJS ze9_P-Q|nr<-5>Eq+Bx<~JJZ_GnFDU`$QkE(b<9i3kIu+CO#QAgL7T4CzGd^0^?srS zXHKP(QX0LMpGvyzOc3EYV{QuZt&qiX#aNn?((L&&-iJe%W=qUFi@j=xbYy;aD(b~1 zbzeBni}{p}_A`xna{ZCajR*w_*i8R*PnDVtt9Sg&RQVFZmZ$x#H%?%Lpr+nE0OwTj{&mIywH^Wu5h{ zoc^`2N)me?O`rh){MKmx*=YX~26IDO8=5aRrhhldgvrT>!a`yGwxNI(7ZXzW`OWuR zg8=*aSz>Ot@$(DBlwX=30AOKhPF9WK=ieBP!fK9+wkD1)`u4^E{6@A0#`xma`liMT z#`;EXcEiR$cO__g;zImNt}A1jkO`=Ji5<$78}BWf9@4aR>-d~ZxqOsRgzTh-`)mf0 zqbZ@`-BNO<20y+Dq3onYVj@RjGwR<)+OdZXSmC;WG7}NkFhxO}hw80bNef=QJ)hN& zw}0p=UsSroqk*LyIlL?09nY6OU$k$wKeRr4U`fpe8ZvKq9c8_4SZ39|y{4|GUA$yG zJa4d`kE*y2aLVc)^CmeYY@@%EV9HvG>UYxUl$K;&^%~8lQ@S*6GA?v1yq)K{^kbO@ zJ=kiyCAwa8jCZ=SvsnC?AGD7al?J@%^vw9tuAxdcd)IVVygPgLNJ&SUo@y zw+o^mgr$9A^`dTF=6oDOcvX!cp6=TCwiAh1CK%>?0 zV-Q$8Ke-tXx@FV% zgFI7>lkYm7>P;F*c=e z)@mp>mfZ935c%St5+FbfqonwT4-RPWLH#-gH~omGnWU7&KzgqBlk}8v#6=l;&k_pX752&3F4;d~SPkk1jsk^mptO`RYtY8ececSXy}>-()kuw*!sq zzTk5~8RQj8hm(?N?+U8<+-I4?>V?N5AjT83FTU|RCZ}FW=7pIk8Tk@`dQnaqj8JaM zyEm-8TS@QK!TZM@hlvtK2o-Ndyq|fTEJlb%y-{dlXRS7X5gAj0w zE>uTaU<%A5z;^PM5zTfO$GmTbawmXoR$2@;aMnxaMQGtbi4yeA2QSg+pv7rK&)yH& z0234yTlDkiDYp!o=egeLRbK*$Ar#u<11$)90OU0d?`|t6N2n;_q{NQOA{iyF4SuG; zUBz#@C=a>U-}R>Ewci@tIiOi()!!JuFn(^-oPw{Grx7zwxyjRqB-hxa>YTjA2M_5p z2;X#%gbG&a)0`W>Pjl{cziY1f@!?G~-)Md;Jh|qkgu>UO$~vZjgvaeMJoOHX(N@P0 zk8Ue1@$9(i3~~vjJq%h#gie#QF8E6AlE_D=!CiH>iI-@!*=RX9;cGw>WJB-TD<1)v zan^}GOZW8J9@hs#CwD>$Hw@)Y0-AzKW#dj|g{^ZaAv*ZrwEtm+?kF^b#RTQ52`KL? zIQT*rntGU8ywUD{mY(%llo~oR%VV~~pn}(MOVU`%kO#(F>rvv8MN*|M00RqC82*8- zT{LRb6mR(gX4@=&7$gC`$UEQ)G!=~mzCPB^s>EgQ<1?6*&)qWy`g~_p^D{M+EAm9! z9=GR{grce~U{aQ~U%`k4{7E|-q=VtBfiygFaF?&K}-*fz#+(0C$**$Mtjbxa{ zFN8o+SLFFz;ODtM5m$na;2EvHpgvPKr?tg-TM%BrAu2y7T$ zPd;joLH^mPcx{r9LN*0T2Q@4a9)+q=Hl?cql7z2!@dy*mBuZ&c)6 z5g@a@py?-p08x2-jR@HU0!}zNm7L`G+vX_tM08)Wcf!OExH}$0XR<3yCT8o`ES3q_ z<2hF(zo2h}W=+C&-#<9_JU6&>9enj0iipffjuvt=X7TM#oOqJ|#54NJn2A*cqCK0f zMkOF!52MT7`pp4&HVWt~tbzn0kF+Zq(1z|E4#~8ug=n3LK_(Q|k9&!1%w{iGQD5RF zKVm3b6$G6Sv@B0B+>cqxs-tln1gIc<6c~Pd1OOiZN&#Yqa6Isy#4JkJ=*7|KSDu!^ zkO$0Q$R|%k1tJV|McVF3TN_~zd_tvLFR1`HD8~wbda)}#5JxT~hB?nd!~Bn}eRb9M zy>JGQF}26g2A@@6c#yoihrp6FuI^|iO7$raDv2`ey&c; zAo76xq@KQzdk@J8d_5~!85d1WYz7)|Yxp_eL&0G`Geqv2#{b}~`{RqA^d=Ejn z^Lio%q5D7t281SIK5S*sOpV?TXxw=3)u`V#S%bYFqh?kuo` z^5jGNbIqRUKmzzlA!=(T!Fl}as2t2RznJ#6(9Cileulv*3PgD4`8j2?3FW+T@O;!Bl~GF9Z!MXaEb$|qGFYju z+Pxzl6s5WZzEK2cN`^aLfm6z*7H;D{DwM17*)x5)7!xjC^t3=&yIb6oXlgmSeLVbj zk+VYTH@P(vE)h%2dd0tu=J^D*^dyd^q^!#RF2Os?lmR*RElc}ibgYLb@Ounoo?11Z zJ`G|Qe-Wf;4?@JJZ?clkUxWrs4^{G6xp#}HAd>tEHY#^K;M<>;*k@&47A!fn_%GKF zDzC{fP3u+X>+2NEPkMb1;QKMwg-MMet)94pEYaLp^oD=<1gq*;nyQcu)tE_}hl+jH z$Sf<)LmFUN>|w)BB6Yn@mYh0}i2IfnI~s_1KW&CyBPzZAH2?HC$XH5k> z+Q|v%6v2<6Eg%?J9EuMM-u{(xWC9FRVHcZ_V3I+QK24_J8LlG5LwYr1WEhRB@Z6^L z1P;c1QXYBcdmwjxo4SI3=`-VY!S~GI&N46Hl9G~?c`;WcmEPoCdv@}Y&stu~%T=ek z6Cuy$WG(7B1Pol&&Q-%GaLa+oSu22(l~}ug)Iz%hd?ZCuVlMM$O|C(QKupHG6SDmM z@krs#b^JY?G<4@I$V?7l6;MFh5_F^|f0=y5` z-XWlPGoYhEp=!{uU6tAeYwg)54^Gnq8QCPDKw|@hk*$H~b47BKV{@Dm zzh?~yD}Cv~YNcJ@LHtRei%L|5tWhCC_*07VcmO~S@qM8{YeO~_Qn<+X&+o{Y>rX!l zVsS9s&GS1SOh73v{P~J3B*;}l_z4XPxV48K;_2A*SghRBp1jD%j;Q73QUij&w!95U zHceXgR1s(wKO(mFHC#wK6QQUPlVyGH5*3W6A3_3h>^1g6J_Vh$|2T+376P~iS1(jE z5TL){#jBmPO+=n-v%WgNYg{kc4_VC}u9gl2@{sSD_BV&Ly&iUQdf<4?w0Dgwiy~)t z(_nnWisM&ERzdSpcLDFL@yLw1 z2E$Epda_(huIcjUd_Y1z-+WIi^@OF48Lp8ff29Jg3b6x`>)1zO-4gN%pE69dXu7k` zfloV^V!a(#m}{iIpo2BASMff8h@}Sc9R<}wSwaT40yTs>m4?5aO!L}Hjjq98dV0Rr z$l`UyK}@&?g=}|>2DHCfh(V{w(N}fqJ2jEP+Yz@T+#T$c z2gO3U>%Cs>T3p$s4Y0$9vp~FEvPq7e`Dv2jvUPJ24jCIue|!KEiE?#2JMx3|%PLXcA`%Ot_KLXVb9jcuDM2X^)mh zRLlb79%z+DAEGkiY6Fo)9M)_N|56;3nk> zgJYfC@f^3?jSAd&&ZZ&v0Eh%%@79@3xuYL`l&hdb7fwSKqKBg@eXsoiS}SnSp-=93 z*Q)ppd0E;8SeSv*C6K#6svAL%f=?Mo7~NT=8q_7HYc-SgoBx~uE<r^cYj!CHM$$0IsQ?!qNSrqQGYH5fgJt^Vl9$vL%Qs@82=*W6B1{$K+^ z9`5VQIcVLMeZ@~A`L&2E)K-|m^FgRoldIF81F;O~^rhm3eH5U&!_oDb7eFh^HeuU2 zTP2~gxAXMd$8qB?y+{Hf$ft17$eV$P1YiKc1OxO#s~*Zk07H1MeGAg?QW;Bffm&8B zJn1&*&e(mbQXy@Za8x*xYuhR`*gGILwb+0$QU_xBiep^?QALK0fIe+La`BN4206pd za;Gp@k??^Ef3Y__Y*AK$-mB;iYSiwclawGg_Em@^00luT2y0pSd7sDQR3-`7`r&*t zI=!1>Y0e5J#sfwnI90Yy-mL&4^P`MW1_V?bQeNpAEF5&&3?x1b1Vn(I?IC=#chL6C zj*<@%{LGO~ax=^fL9VODmmrr<$k&FT>$Ar=6m*$D70EkN5Bos;6}R<6mM8TNlWtZ^ z|AnGI!JI~n${34 z?`Vb5(E@ce29S{cd)?Mx|fmlcNS=tHoooIbS>#4X!9G4ONYarG{E*8J5_cSH37jgx8>y> ztz{Jt4WosZt)$VjLw?vjxRI!kFDoq>2^=l_03Qzme+34M7$+quv5*u8$DuSeYLZQIys zc<2b_WarPnk2yDS&cA;Xgn5#GoZrpUS?8~#F$`OzZd&Q}F z0BAs;ZE~|e%LSV`S-rN(j`drG0aNb)(b2KN5SdM5_oR}_j71p;B4`IJKo)tRG=Nj5s6~*L1<~9?ltD~VTQTg? zxpd2S$s6U1RU!aLCYdH0Azn~lCg$+5xeo7ta2T5lqq*LM1x3XP&5GjoxoXgks*R03_U2Smc4Ul!tCiHc3QUA~ZvaC;n zHcSziHdRi)HPSS52B`p9Fq^y$-rYXC`;3hv|LhOqMq`_*QS)4GLh?(Bj zZWMa&C_vB~XyA$`sl&r5$r+x{_WX8ZW}8$o4(E-9$0jTr&w#E#mXQJgv;-UdH#7R@ zw6P+PbnZ&PiOfv^kqQV-m+yL`FJ2S7Qhw{p-?FP&x}IO)Hmg85O6%dg>*|82^ZZZ| zC~%n;LsBB_J{q%5HUh*tF5sWD`k>2oU46PHKHj@)uY$$Vo~s1%>zQT9NCsg~S&)T| z8*~Jg`F}uNZZ})uWTex&odD(;nXi8Vaq&;BeKvG&;cnTJ2zIFCKD9wur8Az^9ebji zTCcsVD_B+Wu>rAi`{93d6+Dc#KMO47>Un5Ff?fd^SgOIsUn3S*03!e>DT^custTqW zZl#?!JQTm(hh$1W`=wTqpl;MVH)BXg z@7w6DL?Do;lH*vDsQpY=G=u|`kxN64jkQrwqq+rotykTs{FL2-++IFxdm{~$(JLy; z{rXi_IbY#%38Bv&bMU zTS2-rsc2sw{VnN`TCh7`wV)ogut>bZKVB?&V2|G4p7kCobm1OOD-;}v_M~N|Q*&)k zf@?KK(F<(sJhW+{O$w*x5o7dHD=cM7v4C-(UgcyjxN1B}6MIUugQOp1J1>g}@L6X% zDY7tH^v{)PtJYD|yj#C0G0AH-Kk20!7ZjN%&CZ6aRBTlqqCSEmM7M(^UHSXk!P`EV*{ zxVYoJk$kdsks&4kXzF;J$V1|NVxyWUC4XdGv1(z{6Sc2S0 z0i6--qTlT25>cd%2ob#G!ekfzwZ5X*BjQtMqm%fH^q@ub z;BD4-bIMe5t_VCLLD~ZFm+nuQ?;>E&v|{jZ0yK#l`nsGuE9D*`9`2Q+FtC*zNe+RA zPnAcB11-Aa=^fke%gL^lwrxK9mC+AcX0I^-zyLLbal=oh0;oS9$ODKA%Lr8n==uL` zA@a>f3qkB>0D%6Vl?(o(xMB0tKcH)DWd4uKzx7JfGCg!CUM9NJxAS6q%Et2MB!*kDl|@W_ z*_vx>8?#STqt_&A{crJjYoEm140{tak8p4j%k?&@ZSoKzhA;mRN;&*g4VD{aaXp(t8`?;j8(bJy@FvL6v4=^L>2>ff?0gVnYwwz(5i56IK#5blKOD~v%TIXxI!5e7~=EDn8 zeZ4Z79LEX&%ZU``hnyE&HSR%pO(D}x_b5!POXJT^wTW-3nnV3Z@5+5tZz#{}uK<60 zuJR0EtmA&3$;F@TkDMz9U3*)Xe^{!wj^u~)r$Z2aNYDLN9v7EEfWjSUCzMbgNGt{H&HU{DBGTplfCRI|haN>29bVIvB96T95GQ z(xyY{0TwTSm>*6F%qzK)qF5On?d$1;?sD+=a%PWdp0QST74TP(8LUb6^pb^yA|+)E zb))@pjbEG9P~;mJ0%yv1`*GRfbcepjC)A4U2{5u!_*OD4%#aCk7hA#BEC&d}3rY*w z`2?G~AHF1(%a=J!b1Ww$l8F4!w7*4~GjmSWjTgo{tL(aMqhI17b?n$%B6oF!3gg^C z8(G9YvGQ#jOo!D~g7j^{w+n{}wrEjnQ8MNx3 zS2pcG3)+9w79AYz&23B_{^2|cisgp?IZuLJyoDWFbM5TNNxaKtXkR`JT#DZd^?z#W|Jg$GN40;qmiynejf|~r|7ZuSe`N4~>fpC^;HQu5zqr2s zd$s?sh8Il;0+ghm_2QAA{}TS+_w*O18I6U$v;N<$R+p=7#;mX*cpp@ztbU&w4YGc* zKei|^^lOlB`~tLM;lxocWzeOHe1Hx9N%^I7GxDpiU=6Q3H9S?{&K2vXC!=A*LoP6_ zUiM7;r_y>r+o>ScgM-dq&H|Nq!4x4tjo9h>P}le?^lRdM%&}BKUSq^}3RTa?F(*5w5kic4&7w5vH^F?@wIC8#7JZ0DY`Gxh>B z0U*`__O2OhzENmC(&Gw6^9+|T?@se{m)!8u7`lNo1QWPvFVr5e`NIeJDqG^Jy4&79Yx`pf4(3v_d zQrr0huuz#)TDb=V@nCyQwC2?g5kGyXA24g4-HmX{nkD^77$~UX#68zCDSb%vQ+Q*& zliRQR&U83;2YI765vD6Ka>vQEh+}#C1Phmr-dJ$kNK|>Yy+>B>eHgvdcV;{s>mZ#y zM|LRgELsU%-6l=0lg1LeEh?ZFRn-fLFy+D*pbhGzBr4A~W#|RoC{Oa$Z#03W$xZsds5I7HDdUw|u@NP%!12M7h>(F(v zt(!4Wf<#6x3;m3i8l$M!PE`zgaCU&f$e7&bwpPo46R-OmRK7qA5iC@`NZp{~ z4%}((9nT0JsR(a5N#4A;*H8(HCc`1N2%odC^%d-OaRCjC2|1XktClM_ z3jrHwEM0+&%bb-<(2W{C_?32p689v`z=XOF;T3i+ov9Uo6G(a2NbNM7CW{@EYr(cj#C&0}%~RL;S9#V9^jP z#@-Uz@V>CzY(u5q?9|h`P?0xP{U97%>ed)rHQ7Xd_Tclj=3+5c zO^dI1#Q}?;WC^VSM$;YT5go`=OX<>qk_Fdt!s;vL-czTEB72=J-OT$jb(k5en#gw+ zM~Ini(&0XT2<|r3**;Y88F_BjGZxCH9)FtJzp^!6AbsXmw)#{RU zM(a)e{Nb}`^w*F6T!@*q$n!`Ool&YxnGU)6`6`}{UKv}wt6Yl+iVNm6d}_FaF;?+V z-otZJ_l|+5yX;n*hvh+C>0nmg3&(2}&R2}oye#<5f~FDeJ!nO-52!5+|46qSR_n#^ z3+2?aESB{Qwla1HoJ8E{>BM9YncW%dd^-FVs?EC-<7qUUgL3Mte3Z1P>LDa_{mb3a zYb!D@c#GWSb_rEz)Qha6;r)l|=;K?;h^fYn&e~F%so|eyk0yd)rfaj=p&%EA~_47rQe6k_gA~PmV!bh zN|@nReR2Jy0u+-eXq%4TlpUD9(O``aaUiUEvfTVS>D@^+DyI}KXg%YtVrcF2DeC*p z{4Hbgz52svLCfwfpCBfst9<}MGUe)}*afMCY}n8_{Qh*4`GPo^k~(k|TWty$25G`_ zMtj935@TW`03}({x?kA;L*J=9npo9YE=4dDYCgv zbt$u}s^}AV+cc@N?!HDCKS$oY4JB4+#7SS=rb&<~wsfo!KTe;diJ@rznOZ13_Lv(} z7?nTTgp9gzKE5l^oT2%vOw;kKuy&h#=PW^1CnI7#V?I-!F%oIhEWsVFL)}%Wyna7{9O}-C04YUL@-)hdmqEA2rpWk0x1Q@h=WXNmhks5 zM@!Ef98S0D97JC>DEr6hqsys1k@FxyGYGxLB%0pT6Ar!nuf4{e zg~iaV1vGg^a*7}A+570o-T)}?Q-nr1coZltu$;vSAB~}p zZ68w|K)GCdbFmh+^*95JQy@8}Dvl446;Qt~m1qfEg_bfIbs-D3c0lRaW_IZ!Fv&O` z$;d(4GH?h%%FA(L18ZWnrQVhH!EUc;E}RuMD`}cLzelkh`z)e!-3qzP!$~L#C&6m0 zCGO?-K}gDDX1nVI*ob|6pMS_!4q6k~n(mx8I@`b0P(J5Z=AmEEBP|66oXp9v3Jx2> zak{p7eyodLs5Q6z`Uy7eia%-E;M!H>TH{WW2mYY`bngd2Y8{ScNjdbBc=dN8#A}3U zMz#y?${kP#*GkkswkzHK0i;SKLFEM*iAY zoSAebFz|FpPibw%Gf@jg-Xe~kg-w4454ZUyI$CdLy!M9aV%B^tj*s*EH9lUQi@HmtzSi2sn^||`%AEr1JBpwTp9L0H(TDi%9koE-+4_>7Hi{&Y6+(w@ z`<9lh@~lrT?W7-2={9)gS(6V|6gE|CEU*PlM@@=%; zc*XHnvG__bc1>&o`R+o5JSHiXGom=B*8q_xKzzHMC3FesM4=34yTdwV>X+#=ho#la zuUv%;K9s2Mpd4l-m{gUt3xS7B1v7+=R8Pr3aSftRJHGIIrDE{7Yh9FxNK7f#lHJOT zWd-R^M{rzD-_IM|`{s=Yjb&YSYm&m=Z12j5C2NZ|yNF^p)ilXSB{}t2ADX2e)b6_r#v;>hp`DBqzGl-!gsWWx-w zRv6wJliDN#f@dPBbL=A7>U8Ju+{UprT^fz9GvMmgnL%@6ztQmlSEMm(YjOFE7%1N} z4$qT{Da*GfAzf0+Pz~P{OVcT^-ku;4l+>OYnM0$axDQM}4_EHMk&s;O!f2S8nxYHk zXHF48_ppU`N^k`my*v&_dJBS;r#4iWl_<0e=R{RJt4285tf;IY|GBFU91I(Q-6zFu zorEVWt!ndDIG#@Dk_|$ntsRS}wv(xsr&jVE7+ZLu_%Aq(3sA)0$Vbsho08bY?H0ttk6Aie zvwR5=RnZ&JEKY8uV-ZgAYlPQ^z$9W2Z4xj5el_0a<03 z6bwGPe0x(N)jXHygd7nvYIs;q&eFkzT;vtu9iZ&fH*btW`X%)aH>tY+M>I4_tG~Y_qdJ-`v4K`rr z#3*Qr)qx1utSEN|jcBt-8Qz$S!aNe=dGne1+9Y$#m3WT22MV-6zyPf9%(3%8o-Q=v z1Y{ax8O&2Ie;w<+$_|Mx!_aa*9br`+%_VnYi+*o+jkpVXt9UR6l;8bjjM;*u*;sFCy7^D7J&Fo*)-2C`9Fq=mj}P zOu!nAv@{9O8PoxO9w3tx*#g_sK~l^YJBj2_gChu7(5_4j&5OJvb-CH>%5lEOE&TXK zodmrYJ*eR%UIcd5*D$l1iXTV>l`j!0x5e!Agf{7f%i+lZC4Y97>?CuziVB9@SHNB< z$VxtQY5n+Gji7OgPam@&)J08O+6KK68Qa`Gqua7Gg4)U{hP9M7=#23V)zF6Hcq~x! z;#I%7)*{!IB?R51&)i69mn&H1Fb2hMI_c~U21RR1FT!o6Vm&G03eu2=KF;`r+qMGT znSufLG|~R6rU+Rd zns2ie_zX|2L~sUYR&uR1IV*lj7hd?S;3T0+AX@fcU!+%zqZ%`5K4p>@%^$&UrFRy# zF$*fV6@v`c#zJrUbBKS{Do3`R^2}F-Bdy9_vJGpjS?QMcSRwvqP~bq&|E^x{F{4j? zskZf05bkg!7KcVM8rb$W-6csK3?yS-T|%$0jOrr2^MYW%))%t?yl0p69HpYBL-K{Z zVp2z8I^B_ueCrPWyqu~4jYUzAwqvS4v+ra`8F@c0-_Tj7V63zUMHPSc~QzftGhtt`W7K-%??L7KDJ{g`%<>RAXModbA> zw52IHm{_jRwSClHFC6UXp6*UdX8Y!{zglp$%A!P>CFzT%l_%biM^zh8>2tKDOF0*! zh>yUBQ}gk{`V(F5sHu`LDwMVgB0vm8qyHlv$j(nN}9VlhfKZ)jid%o<~G@-0}WhkStppbk6x`R6KYz0rEvh?cik+<*mCYmK952aLBUCs0c zF@uH#_R<<{#UM6L88;go#UmMlPE`l+HBDXZm_>PwRM@~M=YX>4k0fQ;0-TeQ9TTXX zRsu+Q=VZvNiVMtBnS&x$3(|L7olovJR5-O`4peJ#Zb_cnuVjqLQJ(NSo~_Tkf4gZB z`?B*0_48>o;?KwUze5-@{L6%)Q=GJHFC9$q#S5zZxuhN$Q#}r{01%`*-;c<)zO&pt zNpbSa3-LwxM8M{L@7L#g?Ngp8Qk>wTbm}AK)?ASCFAB>I`4`3Nn^W5LpJCMI^`wY* zSZumSwi2k0=t(;FxWb7rL#-kiw_(72egG2T89EAI-{8wk8Hh8|&mu(`E|A>fv(|A0 zfVx&D`X+eAA+CL%PHRg9FXC+f^u&dZ!z!H5Y>WXGvTj2GA6S_%Si5R+;^JaqaVl2@CG}CG#TooL6aRbH1)}}+y zneU5mF)=NHjU3-+O=Wy8%BSEUy9#pZT~MeflDb?W(1Ajxvg}1y#sD;>R7t?b2&|?C zz^_*p3~&5UrprBH8T?|v9+veM(@jw(f`JBnoT23=Nc8{bM!BeqEZ^@g$o(!nnGrwS!{b_ZZ}4{|~%H}Ty?P3(>l zQTO)WT@a-zH>dc4=G%_#>lgsKdE@_#q&)gLP@*FbX%3F5NJeYb+@gn4ykMWqCgn)> z-7CAeTYGXIe71d@Kj-hk1)|yIYu$pV#Mv!-MZ4d=QkR>T) z-bZp7w3hOF2&|9cMcF35_1*JKU^ROGOy4M;|I|gnK=dJNqxubx<%TBztZM&l7VyT3 z*X_;F`XdW{JQ$Wr$EHRoEGOJ-c6-aM_B4&S_}>l|{#o|l4i^5mF#G}we}RR+z`|c(;V-c87g+cUEc^u){sIesfrY=o!e3zF zFR<_zSojMp`~?>N0tF4=8q~=y>(E#|6d#w&$Y)#6QH$|umdkuk6bHLx?qeS$5LW(pNV7xwg1>rigXe3+ z6Vv&$AJQIR>g5VXl!#NeW(Dh-XW7)=>;`C?xIzq}j|m#6H`N|VH%=c+7$qODObEk> zIIU`ZwT*nNRf1v@fOU!fMLDga;$o?vAN8jTS}f6zQ1qI>K}~W6yi+6vBbGwQBAG-X zA5nl}eBoTtL!b0g?nRE02!h6pUqsdt4Wef*|7>$1<#bO^F3A|5YKQM=9KX2gX^RJ2 zx-eq+qOV2gj$WE>l7ELcXb$D-7=VySB~A@-Q79psDKtu?2BW`Bk~&I?m1oz&S|TTI zy^n!aqXKFcseD^3rxhSxI{yo^7GG17|6;Fj)8+E;!IvkSdppRikejD3Eih!zDdYM~ zY0*b>Pca2q=aWcyZE?{>=alBN8-`*ilu=9Kn$t5(_|4xF?aLI`{Q_Xd`Ijs!YlX6@!M6@KZ+LU#)UwcN_W1%B7ani0AmOMbm_qc!ss` zeq%trGF}D*m$-K6>8%$y|A+gh@%w=X?U>` zv}C|JaC!Z>u~G(?PSEJX3CzBir|ivKfp|}dKn5}T2C3|>?Xbo^#(mHz4X6Fp9I1EX z;=#SWR&f*P5qxy&r2gwUM>+P{+pIrlPiuL7dXy>cS>PUpU?YDocc-AmS<|Km1I%~2 z(ld=zEu-2+&ac&$%G8@5TZAfyZMq%!e<}(c+5|RNzy>gdEeeb=N^AB zFH(y|o7Xl*N$thAzr>Qa5RW#Ms;*WbrB%)fXee$JUKV+yAh8^*+jd=p|7UA z;=w-Q6r-22)zvFc&ex~v&Z??%nZjvKXo=Q`oX34+<-Trwp#5#4FL}EuWc}yZ%fFK7 z|26Do)n-);$?HLN?pS<;L5Wm0g1H7gDt`=Or`m*yeOa#>Lc>VhBG7o@EL<0tk~ZKLf}A|v0cs(J}EP{L-`yo`Am1Aciwp61gvDPheJsGiwJ)%{^(1aqB*Nrf}|jHU4BhE-{?KOM}FmK%@FcUpuG-=3ED@NONn;~GlzlRwK6P? zu2P}Nujvx1FcuIUWldbdx0(Y!PXGB1z2gk3=E9#ZkQN|ynSn68ILnDfn$*M4(U#Bc ztRg5ema@8$ms2@9wKY%>J(1=SVfk za6_#lg`?3)G@mso>fJ-~NW;it`rDAhG^5-nrfTfI(Qwxi@Xeg&yca?}KnzwC1Md>?QO3Pav;bRab zz!TRfOml5(hS%9op>EOf!D?WlP^1x2%0z;TCg~$tjdH-M~++G zFxB;THz&5bh}FQyVVgpm4>t*{1#C?38@5OY_cwgMIfgpCCM0o@6ZkfC)CE041$ujO zJA1Ha<;ED~GQ~J!wAAVyHX(a6Os1k`c{pMbeQqHA9BalQUO_TDNWt}J2K27+5~cXxLU?i$=R zxVwem4#6!zaJK-#-Q8US0fJiy4nN6!J(+ydok{oUbMeoqi+#hzT6?eBRPCzuKJUYE zJcrDiE3s`k#V37)CQOoZ`GrD~d>?{#zh~>@mJw$y3gH>m6gDYNRL2;Ur<3w^`}1`^ z2omVh;u5t!{_uvYP|wpSIo7%|8BdGbdyf2_Y~#>#_7+1tQ#NGeC|bU2F;f{;Kj&l5 z++qxTM#A=c#HIU`jT?h(5%(SkBa6IuQ%9sGZS* zpq7X!*b^{khrpX7o54Rv$R&ig!3{K%QEz!VeZKsZngRe9qjW; zKk#bOpqJrB)$GQ|!!3kZ<<_zaK#HM=$0KC6S?r$Dr|eh9wJ@ za*z(Pme2XHczk6@SUo3TfL9vwN>fM04ZRwZ(7_|O)v-68+S%nbTLpX60TUB-&ywR* zGF0u#Rj0klwD77WJmXOCWM4s_8*J$qJ|##t?cxn4McvzWw6h%TMq0`ZP@oRaM@sFrec}H9qEA97RBoK~VhKHjBuDvD)AghkqFDdp+fq(z@ymoSv4 zTK8jW>Eb?#L_nED5U{#lt|2*g=-pbIkWSSL1jnwPY6Us=2$MSsFmIS*PA*HMBP6WZ zk`;|CdtJPdK0%>5DFw<_!KGRruZTHO;lTCY=)M1pg$cJQX%|!mNzQy%h}bG4lqNOZ z^Cy?+P4#i<+$N1Ln?JZXrQ+Ryi$U1vtQ)N)+a&hbEXtR9(gEw(Mv%=%z8ivXxzF|U zE|tfZ^?3&5)OSDX{b7^~M&S$uC9MPx*mV^oa^%4qQN9@nI(JiSr<<{SS~ZfghjX;-ZRs`6!R1KPd8%J_VvVm8>8(a2QibJ;eJ^sw#e_)OM+`m(Kl`!#OG+GWHYC0@H<|bmRJ7a*VI8T#f8mPu$xzWpAk! zUED5;JQzV(J>kDSbOa8)5TRPADkU62fkPCTHyAR8lWx3LQem}<&A$N-^wupIzARw? zo*WSMi0w0_w9|8Ft;2J0toX9Vk+YWZ%(eX*zOQj?gsHe@fQb}~{s==AH$+o~H{Q9V zI5L$o{3wt_cwU>#v*EGijXN!Sr6Bpz!&Uv$aFyc_(`cow*p~XK(@DmV7TYOr_}Rhk z!;jA_0}M@}zfmtNe~jvW_mlmqU+YKuG7`+rLQq)xxlC3PtA^w1T>N>rrNU7p+aO14>z*Zcxgn+X@EQc8pHn#G)HZw1^n*I7Y{ zEGuMD)Cuu!bZNrQ*mj?NlohQiT7UGWHwEcFNIV5ebFbV=w|@x5W1)2>=sW$gJuE%A zS$vSUcY5{j^ozyNY=r(J{j&d9u0Z`K7W`)vO!i~x)uUfap&>|gK&-a*!2D_47+SzH z)L1265qRlfY=f%zl*6s7jD(G)Xp}^A|L|+MsUj3y=ZMtT+Tz0g!>{E5s*9!(0y2R` z$}s&2=Yx7N`%tNih*@Qy0v65NXfX2%y4)?!=Id0%5(Vr`k|kN|wFNNP>*Drfa>_SK zPsCn=6wtV6ixKnMl2z6viE}1yFi({5&hvE+f)BDx0Wfai!s%JG~Y-;ZdXw#!#%Lb}y zot6TwX-eEhg>y{>hT4b|B-{D@CYD4lLXUZ+)&6(CmK4S%ED_r)j|>q@VJv!uFL7l| zt|y67{QX(41sePbWL_ws<@X%+FVht6WjIO3~ciwpnWfgtH7>I2ycdZv_gTz3lk(Q0xLR?vnX z+O2Im^ucWILyYsn+#!oiwWyiT@D_T)yk`}BVtC+@@D0#WY}G|EMY?v;)8=oK-0%O6 zNctR}qw4P z0G$D#GXQi3fX)EW82~y1KxY8x3;>-0pfdn;27t~0&=~+a13+g0=nMdz0iZJgbOwOV z0MHo#I`dzI&OjQVXAV8udk`KsGI@S=+u&c^T#rtc{~$k#{w6;P9Q{HmdPL_QTPcID zCw9U$fMqqFn;jv$y0V)W?CZ){>rdYg;oZVh8}!kiPfaY~O+Irn0jsR$0_ths;*KDl zRJ3Y>{FS8kQgm#cAmQ_z=BkF*f%Stxf`%2!gt*&g8yfPFpiQM!u zNjZ^ElNkonytY>N6k0om?gSIkd`WlaQr9qfAI@I+#Tc>=b-cF-Nf}#(Je{fRN@u{c3;H zB>l;5zMr_({(bDfNMZca_TX>l|JxjYg~s6jmH&$0o#=n448}heOMTZpCEn5v@INXA z6CVW^GXLi@{zhjo{xO{quOef!D2l+V*=q0>*{V1$?KxuSGt_>GU=Ab#DyZ-*29=M& z8gU=r4d!CBAA27yl2VQ*Jb%kKrZ%#e%x=S1aMJyX&a^1BIiY{%H9K#hktBzbO3 z9AzIdJ|s*-BH}h_uhJ%?1(Rl;1R>F_1ugOQNJAV|zRNwT8ybV9Oy?Q)o$ z7Sbm#dCK+{&?76$9hqdYEje4B=DD05AF@|i+jtE=r<0nvl_OiFU^anirPsln@u-$axye04X-p zAEkHhc48&MPd2z|)B=4ds6k`akTmM6T#>Z#IhyPY;u>klgxEklkmI&$jP1!-oQiB@ znls@U3^ew%JQYmjM^RC6S~;p{22%50E-_K1iV-8TK@DF$%jF!VM>OMNmxLbMln3M4 zc55kd++;6nsnLG#8%q3|ZNaWtc0b?(N~;29A%h3JP-!A!mx+BFohJtRT^a;k)f2fB z2i}`a*EOUJZ_?B(Fv%@%$3pvLrX*;fJ0bZfidZ##vy`6gxW&#K zVl7~gY{Xm_j!mwW1SG1|LuzM)p`;m7JUgOQjcO0K?ngS|2OqR`V&>>XrFH43@H1xX zXd0M#eUm`2+HMZFX}OG)ZTbFw$V{JdVap}z1T0W1hw{2)#r|-Yl*`&0+{uh$0@l0I z2FBFpuJReODP|RS&8^EA*f5uqTKRaYWaS1&Uo`d>n{c3KWL)7LHFd?wQRh&x8 zJgOkyEpDm}+B+pZi=;9uyypcAe)ur~WSq0*)yMn3ZZHSMz7FLk?MRX)rsaprXKS<2 zCGnD&RSTrm6iXCy3vOQoF!8kSO>nW!)N;XDbc@DY_YcqK7G5CO?Q2Iw$}kbVNoZNd zc3ao%%kG-mX`x7w$!!dNAkRn$#|?P>JaPbgu_VLfL%=UbYBXe*Z@&rKkZ@= zPhTmjYZZTmJ5_2$rC2ur&n=sp4=Y`FdnV)(%}}gb>V^Sixw`KDAn1q@KCS4>S(igJ zV<>Ai2G)eJ_dOl`s(E4h=*T0r(D`8bu67>Rj@NpF(aXRxkL7^RnGIT0wRi}(@xU}u zHTA8B%_adi8-(gGQ8wfi?v4!xSXxeD>f4tJ4EYP5sP*D+WgMo%^t^KyGQ3%pQaE{< zJlt7h?h_k>dX+00TC=weVQDz@PAILc*?Y-9b2?YF3pOA6-NXzjFK>pzqiJj;`k10; zP6O|Of~bvN&Y;baUM}lPl~BoOO!wl*vU?UE9fTb^)~6XPXH`1PFRE-3gM?FHacYaM z9orAr9|?IZe|V~W!gKk*Sc4mvcR|0g28w^r+t;r#2S2Jd`kyNhcbk(MtE!bROWIGo zrSK)TC&Be!*N1;fTO4+KG4ck6zF}?zN!%#Zftz`Ch<)mK8nwx{k_ukK`aSsd25^(d z*_O?5m|`ldegZk8)Nw0zvYw6sv~qeDc$EkSDpBUs2NK_?0;xiKSM*jNKA6w9*(+;U z@I}699M8&NQ;Q`@u;2ODkceF->FGb)dR?F$EfGx)>0$PMCaM;x)5J!oG@L+PU;=Ep zbY4#i!5>P&CW7*w59jdWMs3d2Fqge^s6W0lb>7vzF{vdl*ssScU0>a|$0mNtacLS@ zSb&h!K*Z;T!Ba`UInx{yQM*15+K3@`#5i-SFM`CW62@lLTFQB`l?ViBjkM1=kvTt$ z!X(kUAD@{rY6>5ly}vy_eA(Z_7qN9Veqhh0-L{O=<5C+tZ}03P<$|y0c!T*eby=3^ z*#P=gd#~Ub6oqtueHTk0nEm@oWid5sbVYSNqFJWQ?9Eh3O9ZxEU?*8}UyyUz1g*&! z5NX0#ZZrSNi!btGAtn{Dk4BAg-Fbv*CbGwOG_3r(=Zw>MFwrf|Ee%;?acl^9c{$OiW=m zQ-SXoJdL?++XDox;YjpcJqTj__v&g?2>ON9dl=elh9p9(WEGWaPj3IKn1hXfXATxW zpCx`{4le%59E`fej+VSr-1%UPb=D|X1y$@BO=-q~N{jE`Ud1&yPEWJUt6;l%E@;8g z)M@<=y3a<+X)!pr$zu`Jv$=>?AZxq>v!KvYOMIS9$MVv0Dt6pn*wFFXm?z`s%t7=I z%)#{^Fb7A!%N)pVe=}{k{8iHi`%CYJ>|bFH-uz!+4z^q#K!X*lkd&5@#z zmU$e5B*gq^h3GR3jZA(;P*KhI7tHdu0)Dhx5{=H9iaq4vS6#vhr58>026MT6t`({S zGS--B2;@d8W<32lh8DFTpQVOox{58P#1(|gBw@8`2`Tp6q%8PPOUTOGrR$7j8-4pe zKH%6PSeW=N#KTR)=eQp|ndhYt$RS#bNnNs;ptEQ?cdR@X7ATeV2HL)5-7Lk78IU67 zNDt7uM4OUG`DmWz>bHg5Y|r2W*8NhdDSjH>dSQ~RAB8#%hVsj(`Eo40g-sU<;gGz`N3)I>H=RjcjsRS zvTE-pOV7$CzJ9IYKu#>C+Ba<{XBJnwLkfbemR39~SqN)3$BC=Sq$#*pQ-xcNwC*p5 zG-0{km3@@#Uy7Po2z>iwMN4vY>DNsgt5p9qZJg=;VA{C&`%N3G|IxH@@vo+hCx5GH z<0a59nKtnMY1%;iUDL+nuMeKB|J$_jugt;EGOd5nv;klZfPf%@zIxcgHaBRs|Fda> z@wbKk8Do(8>>FbcJt;(UMLhi7v=M3lZib-;dqcaS(f@MQ1>`)D*aRNvS!Amm8IKP`>)nQ1toNzX=T4sVxtmsRXK%o*w9kY=yO29f-x2Lfex1` zRF^IP@B#$;n`xu!t7#+qgE`B+#G`4W?VD*M;vc3B!L}$Ii$~K2ot#tmqiKVdJ*aGm zfQdL{R^We38?4_<8+$&DkERVT_KaF9ZbRGy=^}fb^JsUxZ>Ej7;KnyK1@d1_8y~)z zHl{)2s&MsHO27(V#s9;!L1kS>LH=mksD3nUpnNrLMEt91gZR<3f!qGowBgU9~w~ zXXA*va{CSsZ5cq+n|-7FX8l)C-x$5;GGp8QskdZ+KU!i}6*_!-3k6Xco1q^}EIZ zwMs*NxP@Y=RnmiZY|CaV6agL28q{)=Oaen^{%Kyoq^M0b*_{YG1jUV`r!~QjH;AdFHx0mUk%K+d70K5Qz z7Xa`A0A2vV3jlZl051UG1pvGNfENJp0svkBzzYC)0RS%m-~|A@0Du<&@B#o{0Kf|X zc!B>SUO?yA;CaMj;(O}x_*u)`x9x&I!wG0d3c&jjpa@^Q@xArRU1k;j46@RWaEYpT zhjD4{alkD9t`?JQlg3FdXxWxNe&hIs3Otm|TW3AL?PPrq7=tkn2Rb}nZ`R{M|C5B?w`=~zgnLzGdEc-Cg%mB-$k1q& zGSd{ZyrTH9)QDXFkW{TQ6|KZ%jr_aXjdzriv?KJilCre#Hxz+DQrBaM-a-d7buB4r z=63n|x*|yRkI=W0)DSR=WDbpq;%9-TUN_xd^1SUZc8{IZwkpD9@~p#?|8d)d+ka^S5yMpWIdZ=|0u(=E?u$1V7^$zU?o5U69{S{#!Es&ji+^Bk)9m zA2;*aA5{V(Kf9lP_fq~j(=PA`zj*o@^5D%t8HRaEWVojS^T%QTfUYxIs?sNv+^96V#$r$Wc{C>4IX@QMP? zKBC%T8Cyaz9;U)wsF~rDDYRLCUrDY>rVO6jXCa_oGL)eXlq^SZbbYK`7%_YF(pJ)1 zi#iw^>ke03?cCQ(ZB!xj*-mj?w_m_IF7aB#PBuYa6C2`snue#ovXVq6M-y_UTxW*C zZmu=L9@-S$;z^;>R3M6L5XyEXG98&~(SsoD9^Xa_D-Q6uVDykU$@{aE)G~{GnKqyz;{Pt@&!Xus`b_ zt5pxTe-jdpOw+}9nw^?|Q3ZopC;sSiN>86G!jS~x6g+ONQ%}`PknLr{$3A68VdaxA z*R(~1V2shQ?2Br?O9YcBEn(eGUa}k-#4t<6`@By3iREqPZ6g=4zNolp(eFOC1jZrv zW{;eig(`g@U!OERo@=tTn-E{SS`*Y=j1l=DS!en(Xs zdD_j$$LaaSFLpVW(;htkYm?6PT}@Yrz(7FUkI(Ht`QFR)+{V($(agsBw;-;JzO~s4 zV+Th%S1Zfk{Sp!pBO~{O@G+5lhwASk;K2mfSi>m8GL9$BlS(PAIiXF!PPHrR&Cyz zSXMYhir!g;}Hy2~p{HQFdt0GS*&!jm|5WReb4i>i~MuK8QIeCIA^f{cIk2 zFF>kT)327SgL|JU?x1+QV`izZ0|qtv(KE3E%10iV| zCipf~LY0>gf~*U!QhhOQYxOAU^|DGB3gUjUOS+p$Srav+lEXySf@U3jkFAHp8SXn? zUwWxhVJI^{q$G1EpW~8gY_yritZFqB3b=%^0VGzn#ED~Hoz7uU9r>>%>my%F*24pf z$1fosOV(k&m8@6)qhuWmm>=4b1`;ZOi>>CdWZk9X@P^5+FPuaN;(tok*?%ip=l8Hk zZMlPgSzE+Bw>Q!J6OIf>cZ-A zWS`H0UY%f>OSTQsbJ$SVw=A#`Po_9HtT(?3}bXK@~FIU5vI6 z*Hj)qz;2SoUo}ROHnPKhG2?a?CH|y|1MZf?`%6`RW5)48!a4IoR;-TJR@&`oXHj_CVtuD&5>LSE0v}b+2>_ zLuVe?$C7pAAh#`kCIZ-L4g;MB+D){f(l?wom)PFhcko#Gvx#Kk^8`IJ0`~~r`t+=h z!mWjaDPPnlSD;f`=z1P-AQSEllgRI>9796h%^jcKB@{L|alpUme!5*a_EP)0+%!Mp zKrT$hA`WfNz)fGB<}A^6*z{7?5%QRi)1x(Hy*u}M?&itY+xPct1AbD5{{8m-drQ{8 zkNfqfgx`Jt`Q!8b$*(Nm$Nj%lvi{=)e=Q{a6CmZs;s07#`X?<4KMoHFP2a9qWK`eX zrYr+O(}2)4AT$jKO#?#HfY3A`Gz|z%147e)&@>=44G2vGLeqfIG$1q$2u%Y*(}2)4 zAT$jKO#?#HfY9`RQE2+kTMI$_ar0REv8DJYP2oRo8~jUnTG!af?2mVlYm~-iI~Y*B zUg(a0o)+I6ehn8KV#9-_D`6JaTxpT`g=lSd@f{pH4tPXM>A?=?cDhHSXA3=?+jG8G zRbXl1M-&Pw98h0!-)b%`txR6g44#szb>GF{FQG{^8Ft2L?%?+Mns=EGs3B;?^Mt3~ zRoaqnOjDmxRlJCLk-cTH%R>={6V)&dFbrqW;%}e9*-okUS!_jsqywc)f6^qb&tTpJ~pPhs*1l$(d_Hq zxmWI@xkI^LzWraJ?`#8DtLVqT_w3{GS6;LK)b1|uwcTCh;!Rd^X>@cNAqua*om7f* z4ss^x0fDQB`dZIr;!*SM*1JeQcZC5QzrZ3MpDexXjWLU)O*@{>T-p@uQhO7PI4C+1 zXI5^w*(cm_!%A=8r@r1>Ha{kM9+6aqH$>mM1=3K~Z z1qrhg8+ayxH@Do9#}!m1E#Hs3?y8$61!IpFj`^5&;QHf)<{#d$4*$UkF#gR60KQh` z5jtL6_erLQ%?l`M-6@WBAxlaOJFTU8`3;e~{L?S;rkAOnuPyD$o}NIZu_xFwO63uW z7L_nn4|Ye_#@4H$D7os**nWysg57c(f11Aa78-VxZXdlb!3fjKWMs{)Tg35ORs45cpbjjT zz2`r&gJNsr++j4YLG2U3_m;@_Wd3lWX^z@&?qcdnW{&hG7&HM>=m@1q%aQVoS2}z z8Kd7jt1v>J2Ckm>Q(3G1j)M0mAE86_FkBfa1eT(=VZ)|S13}!uoyOd&(ZC|$>~D8@ zRz!l}*rQwEOd>rv?!cYGJtB*6rh7Ey^C^ca3*e&SUo~`Ho)t>BEIYcJva{2c8=hJAO?sFsN!sV(9gKQVBV%?b637_EI} zclMf^tVSuD5s>O=y$S;KO-F2nLRS;Y z2pOLHzAvv~+)353sa*scB7%?8IXBWzJ-6;?H|4>;3oIDa&Oqv~f@OJNN5>-8+4so} zrZRx(qMC<~1Ajk(GaF7c#Z4P7uEJ+zZssiQV2>O&WLnuL6HyIK9C(ODU`69obr0Jy zkEwNG@?nUaT({%urazz4b4M=!?t}+tSdS^7-G~Qv`-4&V>WZMZCk%ea$rwar+y~BE zzG)QT4isVXC|Vch5etNbqE~UbJV;WA`lkIwM7@u?-=lebOPs`I1celeaO+k86wF^`{X9&3~T}}vzBMeLL`_2 zW?CPuJ$yhqQMxeeu6%89i{2}R(K1s|#fbZFrZI$&8ocFC3d-obI#|}@+8q^B-A<&h z#?PE8*C9?K9~LV4uyad?(}Aicx*9k+f1Au4n4LQA>DU1EGGKCp;*b22}m9%8Z=j9ag_XcVrZw`F9m=Vk(t=C^k20Py|wlhr;ZFN(M z(7jI*vP6Gkv4A@)NcP?J-VxD0k==Ba%{eSMzG$tB^NkQL?uo-I z6~%e~Y6R04GgRC(>q4U-!oy<1pZPgEaz3{3fpiTBJDO_fRq3|MJh9ZCIR+h2J1A0O z?6Z9EE9irv9*iH$Dr1a*R}kY%;YBW4IJxyhY^G6=F{F0Dm!$#=*ql{b*KF|;mM>>p z6q1s2w$Pp`<<-lK``G8LJP|t;X{br?864Zwqv=WA*33kq!mck(WV6G=oT3*;{v{K2 z%q!_b&=Gel^G$R6h~#O`2fW+q{Wo^~#QR=&HJhZqL#$5?@r#@^eQSb`-7!je-Es8f z2vQk(BG;0}21EA|`cfBCv}^t4Q;@NQShAnDXr zf_2Q4`|u^N&BXBWl!0A@cO1>|TU(&_=v%&rB<`7e`eZWzi;iF_>4wscf6a2M`L4&W z`Gtg4uZ8ZRpp)f!jton$y1cD^w@75AUrkc&aEr<3i{RS@SIdDiHd5^?Zdf!`O9W#G zx|Rg5$Z)Yr2A^h>bojbmw&3R;165jBa+mq4t>oRAl(xdRE;5bwe8qxIKm&&&*(L_Tdu&_(7o(=1)~)5aX>7C#|2IbFFo2le^TM>8$s9?@-lpPQg3noT^n;=6bQ?_Peoh4}s~ z%p^a~v+)tcvik`TQ1hc+M*3Htg@5<+{(q=FCi<@*iXvaX&Y9~w>wkOPI8wrr{(308 zf&z_d1S3Z%$=GbLAvE8pN;|}$>u~lJ7AU;EUr-6wfAYRcKo*!b0@c7+k(82J^uxmn zW{Bj+sNq0}!HFifM;lb%eImT4Pvyu{(L8#1Upw?eYa8#N)*4x6fAMZYLJXEzMyfC< z6e@uyhhX|iVM%y=6MjcuxxK>b_T4nEafN(yzF!Supm|*_{6~vp13lq z6>1%>j2Xgvri}TuHVkk0+r3yaJ_GeLJ)XHkC+chIerE$kw^~7-=!)qYl2k*QTBf`S zC5>Pd!f6kdP%2-XVOb69Vp1QdNh5pmG~4O?um;!cm-#|`4|+uACgNtIgCx?n`9izA zTSWEPj$9-%*bp*FH1I){u^v0{erI|m@j{y&1@2n@HE?1iq@7`XItG|8^E1N4DPvJ^ zH#zgCN3$k{8(3Q=BGa1Y#vq@)fwFg&HMR{eArlA*5aqm`-8mlH6g>T#}fnT!UF;4>%=#!5t9wmn7iC> z6X4OzG|Rw{K3u2Mm)D=0B4?`1EMn2%Qcolj#tlv#MNd`EJ@}q(*X(buGp1DIS`?MS zTuD^s6C<7?j5Bi_@s@9ZIVdlRbq#klom`LC$$EIszGR|)(=2cJ_z6Dr=~^^^OkNFS zRN58q6I-o7)h+JC8zpdvH&C83+RqQf%%AfYaCOYA`Z{>HP1iBdzhuR4em`Ewo`cPG zaMobb&-HMNIpKnm_+! zO%b(xN&@Kukwd$EgL_hG2Kq%a*#q<&YkV`^kqb*ozU#3{hyB~9-`_*N)^``(o#p+4 z#?FDkbqWzY)`eT3F%(v-isGc5Dg**pKwK~?SV{;l1)M>4 zbUJ1?;nAb5YE@XisAe7}!jdfh(N?9LEZZaa%JJ|$(5CdqF>G4B_n+G3vb!x2+k59v z6R+-KBD`>xmm{nbt9C%PTo}?N02rD1Vog$iBHyEfr6V?nV&_V_sh%c&>3Z)8EicGGC;^GLyx1j$?`APtWWG9!^j z^)Pj`6|!0@2#buR%{BU2WbN_|ig?k8yga;|L^3I@2zX?btQpu(=Dc1as0VDG$0|l` zeRQJ=SAz;Q)Y?(p85~9TUi!`PQvTiXG72-~-5$>5nkA2!+|6z-q>j<@4!3SikgygU ziJ^%XL88NHNrU>eQ5KD1(wfE=Nw+#VWzpj0;eVCmj~Jkvr=r zS5Ytge9RQlc-1@augo_X$MPmL;c3U3dfMhElZ3-`in>$xOjeu~eRg%QkF~iCR$YoK z%~l{SI@1XRv)kq zLK7y*x%@&QNxlz3yWg{Qa?6Ob7KQMPY6_baC#qu%%F{{ty8Zb&9|Q?>X>o~KAAfkm zRjB7_lpJeanT)5!?L9~SuQ*;({x3LQ4!2tUgbwz3r5|`TY0%4XqiS|zC^Xk94{SFvKAKU_uh=vQp1u3OF2jfSVS!fx@XC8DjBMF<*L)(WLkLD5}t7=c(Sjc z&keS844)Dtn|ARAlcMfzJK9-}b|Wq226B(50ny-$$BGu?zM>J&9Q7tyZMbYOGE*^2 zy3s^sjVACl=?jbXX;$+b3L;ff@UlgOxbvpm8hkgE*jYU?Ev9^J0i#pzNRHr|DuIK6 zKywJi<_n*Fyf^|yMB9FuLw2)7))n^#HP@`SD*61c9PU$2XJ92ZbCGaH1?fCtc1dLH zYh;@Q&Z2cVliGX@T1i(1%puqh%wml~<3|EeZcJ(pC4y?&41Kl}sYY^%MRek5kWase zJ)y6`fab{UF6t3CR$XF^I1=i!L+00b8rQ47%dVmC7T=ax$LAp-;xN(v_SGzZ-G6qx zywvlz1KRe9rIbwJW-%-{qFe??0`oPoIbd>Hi30g}m)5B$mK6~eX{)7_r)!fIeRf^K zP@ZbtkEx}L`y>(pWfDQa>Uz0`#VTw7qERBwk zux3kEG_ve<@kaUth32FbC|d=WYI(dO=0t@9*L$P){xcRP+@_>mP#GjS^IaigtBg>Z z)O63ET%tGC$E9xSPdp1u7lzV}>wC#DzPfTXvS&SUZ`YK) zrB-xtyD0Kt1Yz}r|Mt)kIP^ka0CSoQDoj=$QVw#@mfiR)hags1~|}Lw`BOT zgaLSRK-43)&y>_QY`u-3{~6^O%>jF z=aS;cRLbz9Koa43Z8Fb>7K;k*wCt6FZeX88ADoZr@Y~3 z2fGhHKD$IDQ12uCXY!HxuaJ*YPZ+E7*ex4mUCoiFILW_r}HP9$Ylh#sDBdiuwB0spx0&K8Rv29Fys`;T8fssH$k=f5rd zucME=R;nIv{ohl77A58EQrhbYE+M4W$e7*VMMBM6)rcdur@L(@yKD_K`aYW`ryXbx z*wcfoWoPFnSR}rDHztYldWOQMP;?t|RHIqnx|v!sOeAtb4>*EG-p`4Wb#!NXHC!)Z z0h08Cv;C7?#Ir^w>QnT+B{9c{8okeAVhRs!OE)0JhQiAqhV&a3e| zB4i{d3sME8n<&GSEqUe3+Z<~qYlriinyWJTR*SN(V%!Q1Z&bF$nIp0Zq}4dc*6B=0 zsae2T?yddvbZW`hSb;Y^rIJu>1kBcQMH{LHfNM3>2nP`{YN}{w#i;@qRKlzbTkD+K zv-9{NUh8Ugw3#4O0x#Xr7!XgmhP=ynjBgKX)w-5I3xJ&<1vO&|dq*MjX%G1JBkGm{ z6E<*+suDQA`N1WWA_sn@Z60G6JrK7OI1}rZ0lEFIR0145qU3p`h9b9oHXrmxo*860 zLA)eRz~+1It8z-J4L3Wi%ag77(e%TY?X`PvR8eu{HUvLqk{ju;f=$>V1l`+LeMz+Z z6m3aWjBJUmfco(>aMxiI8cVSsaaL;+#fUWobwX~~Fi~1J^*g_zqf;&H*o{njx!Pim zC8K-dCmr%N#9Py=iq`E*1IcHBttT!k2XF1%waq$`J{wqKTH<*NmFiSy#NtW50O6YPrde0yWM9$i)7`iG_fNBr-|yeQmwo&`?%&HkejoS$68re$ z1b;jG_~Y<@JNx+K@BsD^z&^6$mby`k?Fmo-*hc{S2w)!p>?44E1h9_)_7T870@z0Y z`v_nk0qi4yeFU(N0QM2UJ_6WB0Q(4F9|7zmfPMUbkA3`c+W^2m{{Mk}{KMDm{{{B( zCl_yN_LIKnn*VC{F;;;BP4oaH^Y%9K8GWwAsR<0$WQ=~l^a>m!w_up88-`^7d3H$hcd46LF z{v?<96ZY}n$Nr5={F8J1gnj(uIsRt$@jp!TKhOp9udt78oicFgk3uFGgrBmHzdGY@ z>?8Ac&g0{AEa`*C<2TNuRCU#6kqzPHg|1y+?2?)NLJKS$$WYC)vZ?u#_lpD=fv*xq z*i_Z0#0NqZK6ya=RZFL6qx}yz~2*S_*D66~vyH*xHUS zXo=*{5CQUzL6n`RLrEXj4J#Y8Sp?$+O;(h7cThP6DmrBo6kR(rIQsO2$iqM#M=*}_ zK2YJ4z4G3z9If=ifo5t!dNm8 z-+s6>49!EdU^qw%1wlnjQO{vwXxinEmVOn89&wZ+pqK-=s$`|1Ks`M&9WGkTR`@mR zOb~GHyz5t~cEUTbrl}}A@CHjEuk52R!&Y_9-9cr<;m(;9aF!5=JH^j6z{KRvx zp5yv|$*#d+9##oQ2)8fvw=9K0Z6dFOdav>YCrr<%iT~4R($+HgXt_U@%W|>q&OtZv z@{xW6S}7b@6ng=!KpK4Uc|bpV0xYayf|(_Xx*%zmK8Hr2Zs+FmohctC9rlgG*RUSg1q#~Rr6 z_?le1Bsvi=N%NWnxO+0?ojPVnERE??@I$IP<55=4)XkO;;iuMDz@}+&3CA@+U`w6f zE%?-k;#vhs7^WKlBjBo&OR)IUsyFn&NeRvUC&)hB$~>`zWvw{I>?a+KBK?FTB9?zihR1aUP;^7 zpN<+taslq94VA~6 z5-ggNY@@?lO~|>sx>CWES+`@xN8)=gi!hGsYttZEG9ibJ-G3zqdQ32Q{!u_`%Sn3t zYJUbrdLs${?U0s~cWA|e_CZ(&gEynXcmz#P44v8Rz^YThm+Y|j%t3G_W!VFrlNXh} zD~3n9-?Nw)j}Tyg$P8ruV|$Ay>`x)UKlADEBLvv`2mpRPe*18!QIT?37e(Mp)g9l9 zog?a~sn6NBM+%=W830v$HM<#W@fwS<#y}J^;&ngT1Mjl?D^UBH#7}KPcjvRKpQU!a z_uIrUc3n-3>fW!xHXiTn?xJ4`?J)=*#~mU03K;HWOESDt0yAwZLjnK%xUPkau?<*uQn0M+q1S!9kppCH)*SJd-& z6-cghoS!G4ePQf_cUFtwLG`7^uWH`2wH#hl(Kv{d%}tZ-i-EE2L^XdfWx~G`E|Mx2 zL)DLY)!zEt>{HhuZg7&)m4So?akLK`fuNsJRf@8Ss77H29*Mg#v;J!{kYqLD#6l~Q z(g|^~@+TBlg6*4n@GG}Shu{u2D~2)THYdi{b+7WyIiW@VRq}WZ})c)A~wu0^}%-W=Qf)Jl_aSGOS?rN0U+&8+9?C zY8cO&9Cq2nsV8en% zsmx=te8F|*o99DHaxo}CU?3$jw?yBnCw$&O33|(yi-m=$wQG_SQ5= zL&2U_bu_s?`Yo8j8N9oIq(($wg_|=}H*v0DA}~E{>2o}(XX|gMPP7*UsMZKvxakR? zi&~8Jv`v&#@j29KjJU@U@kuFzR8(N% zQ?}@?_HJAu)&!0>_T(245!!z30a9BzxMlN%;^HNsX;8*FeYrK#=lDq)x+4q{#Ct=c zXT2xu#@F%|MY~yeulpA`EBB)+FLKRRwP@=jCu3)orb54bP^)$iH%L8wl6+mj7EWD# zpHeJ;ogtph#`HxlQ&>D(#g=2UWLm%1Zln6lC31k9K0|Sv2GvtJDKl~+;`9^L85e6< z&A7UzAx%@a>(oJdVA+@=6dhZH26;obR_cn zCCeqY)^A#Dc0I-lZg1ev6W`8q<;%F4T|JFI3TvCJHhZd&9LYG6C`c=B7;J8CJ|t57 z?4D-rgyX$~8k_QLO@n2D#?nL-KG?pqX}5Fvd%I>U{Mle#FrzUHWqxn6?Wz=*1A!~Z zB5o$ut2<~_E6v@CL}S|qU-(uaVs}H!Ydn!0JNXcbKKC)YEe4{Sk=F0;l3y`LWB;Lg z4oDy%bPOOM#a~IR|MvCfx33`o+F0`cwRYvJud?ON5frW{aYtlJCwp#>~wu_s*zio}Q;a-uIl} zJ?Fgd?|1GwSLgqu($J1Mx(0MU7YP4el-9S_YSEI6N?|?wE6(;Ihl2|W6qR}6;5w9#iv{B3XzUiaKtt%szN0tV3{gMiI z-jOU@|3$%v`**0kP`$NHR-Hr3UpKk3S1F9X&NLfl3s!OB4d_|=)Hmu}M2p0he@&f= zh2}j-@xVI8dacG44O;$iCpQ`*ts#e6 zY}d^B!o}5nj&m6|;O^89rS2N&`S=O52Y=QUsdXp%^RE!JYs34}J>R9*lxB9fwGS$= z=Y%CK4pY<3jJ$XHthJ5jCK+D|*Wj2NL9!`xl!DZS3|%VotLJ)TOWS?eBZsmZ@_MMJ zu2Ln8E=yh`b|8Q+`1IbnkB0l=1SbyjY*6>KZ??({j588(7`)2g`>L?05T%>T6H^;o z$MarE8vle(?s9QOxP4#a+2!jG3#gg~#;dw5IXFK4=G9V%1qOz7-uYj4DkX^ICB{yE zJN#yZePpXv_QG>0$2C5m6FTffj}+~ir*X^fK|vJf!T>(AQ@f=~TjwjJqaKMV-NG5H z4QyQ-*QZ~J&y184*eG@rxubu?_9Xv+Oo{o62lI+FolnUbYsKrVl0T+4qJ2#8n`P*| zGtHKk_vd+84mvJrYZ2tZY|1_-XpQMr&oAP~)?_MaFgDnqj zWu4UcxAQX}iQ*+qj^diPR(XoOba4=NHMFeZddCra#ZhgmvcjL4#mHxw;(U6yg^r6ep+>8v@3I!+V|h!16=x{_lz^t*Sha6|8jk-psk>=%>)={#38B z6W>EdHIK7Nvs-Kqw@);d+&d6^t|+GTxkBHfMMFGC_Wl;*9k$?- z5$Q`1JYnJSk+ZUV$waqGAdN3P>V-#~Z60kz-~S=;N}EqNBQ~~Hbn%4z^}NfbMtdup zoZ=JHPX0B?g^6hReDG?c+=?E95GkdyTE&dR9QL*cLejxYN2Gr`@JQ1Vg z|8jm3I4$ugey2~gd#yXij~Zp`HQjUHxeGevSoX&oZsL`VZgne4IhGy&RVj4jRaI8V zH|e~|bamWt~MKrI)k@3304^6C9^)%_2ggx)9Rc!s!_ zk0)Y-j4?>f^_h#sJS403b$i8~de8ehAtI8lLUUbv&XwaQ1|Hx_Z{vj&@!b z?!bG>+Q%vQS=T@=yVy;Zg4sDljuN~w~`pC)734Xauz5a!C4Ef8I$k=Y}YTRB?- zYvwz3q*{sV>8{^#w!OE6g)cm|xy57zVO`CKn=WL!p->Uv3Imjc?wN)j-*g|(7WS5_?JRT)#}cQ3Bw_@Z(BTK$fK z5}VkXM@BVH7H@D)>vN_0FZKA$@4?G*ZwN`{&MX`fA6WO{;?f;Tzop$p_m8MaU8~2c zy-3=J3v>IWtdp7$#@7>u|6yWh&Bl)8pkAHjL+}7s_!0i_BR-lE{++7mtq$<=w(-~o zloaP6I0z*@r@aW^hCA9wi$F-LW+F|O3Yo<`K^v2B?Hj~)%7WV2K^s$h`lKghY;X)T zfYYRZM3WQ)ZD!lMpEf4>Rt?DQ1;?U+Ha0oor-DtsSda1yt=d$a0Z_!pC^_JOCyiL> zQ2&PLjK@i)ky_`t+zkMH3!E60r=U3>l??n3Bbxuujm|))K0TyBgJlhHXCO^<;;BBS zaB=i-iKqG?;wpjK`<@=|AE){t5-5NOOy)5N$n>c`rr>dm;HOXZ(Sf&C2=8q`A`pb1 z#&qimV{(uYJe5;@Glk)k++NKkWp@|YJ$kV$TJ|Lw!J!oiTX4LuY=r*beKq~Je75jI=0I6 zm?J2x8x(9(nE)~ed0Z1X%HVKJ?NmYx)KXAq#FZcfiqsi!&4WtU$TP{6OIDb$CKB#v zH3toX80HzL7VZ$zPUVaq6Zug<6}&xWnPv^3B!sK*%s~97)S2!vfuEul4$!~&zYb1v zRpjndmY1wR^iQ-|qMuP@q7ef^jmvU(&)9rm`4Rwh7A)m4hBO<2hAri-8Hu`Es7m>u z5n~$Wr99J^4mt}`K12_f1t~W%VbI=bt)eoss4q-lDNkcWz?zf~F@k4J%Ga!f8XiB- z0F1_Nj4zcik!K)nDG%PnfQb4leRL)oZ7G*^fzHLMl#9B;;esUPl=s7frQCW81F~6@ z@@;N(m{^qZn^3Sx>PKa`QJ%gj)ddOqet(*cAeSFZ zFJ%u z)4)+yZ~=P$1v==k6cvo?LJt>~l7b7+m+0X#r=Z}hl_Q%$K;SAT7~X{uJY2;j8x4YD zUS$LiPbuApw>bbhfoK7KV4K;EhZZIb(bGdy$T>QXj{uU70G=@doZkWavNW|rlfr0V z_XPQ2e6bpP{dYlL)xo9O{M&SxV5<{Y0Vkkf!&W8o2q1{W=1K_dCvm`2Ba(q2N^Lo8 zqN%aKK!uVLq|J}919k<-@xY~8g*$M&HqA&_^#P+6q76@d!1;R)Y6}&%9+YCB5Dg@5I_?|#ufu%-Zd|xQ| zuv7^=>Fz+mXHK0+o`X2)WPoo=GJG5aBDg9Arip+`16Qrc4w|4=T~KM@sTO6e6`W{^ z^uh}tVf}!=eG2A$*ax2zT5?CZjcN$;>oxt%aKf&^k_3V1hdBlzlFnL2DfbBiBW%qE zXO!V^I7qq**?W-Z13|mrFvA5;!@(J)^$?5zk~&A3Q8K92fS6pR3pI!9?S2zOA>DHelopCIeX$EY&anMoFd!5dyP&pA`JqYZd#dkW~! z6q+ojq#;B-0y8ZJ@x=2?i$VFO7uaG<=*&tp=v$0Az&myb1Qz&<)IuQ2mlHCB{{S|e B@e}|6 diff --git a/docs/html/training/notepad/index.jd b/docs/html/training/notepad/index.jd deleted file mode 100644 index 507b232e79087..0000000000000 --- a/docs/html/training/notepad/index.jd +++ /dev/null @@ -1,136 +0,0 @@ -excludeFromSuggestions=true -page.title=Notepad Tutorial -parent.title=Tutorials -@jd:body - - -

This tutorial on writing a notepad application gives you a "hands-on" introduction -to the Android framework and the tools you use to build applications on it. -Starting from a preconfigured project file, it guides you through the process of -developing a simple notepad application and provides concrete examples of how to -set up the project, develop the application logic and user interface, and then -compile and run the application.

- -

The tutorial presents the application development as a set of -exercises (see below), each consisting of several steps. You should follow -the steps in each exercise to gradually build and refine your -application. The exercises explain each step in detail and provide all the -sample code you need to complete the application.

- -

When you are finished with the tutorial, you will have created a functioning -Android application and will have learned many of the most important -concepts in Android development.

- - -

Who Should Use this Tutorial

- -

This tutorial is designed for experienced developers, especially those with -knowledge of the Java programming language. If you haven't written Java -applications before, you can still use the tutorial, but you might need to work -at a slower pace.

- -

Also note that this tutorial uses -the Eclipse development environment, with the Android plugin installed. If you -are not using Eclipse, you can follow the exercises and build the application, -but you will need to determine how to accomplish the Eclipse-specific -steps in your environment.

- - -

Preparing for the Exercises

- -

The tutorial assumes that you have some familiarity with basic Android -application concepts and terminology. If you are not, you -should read Application -Fundamentals before continuing.

- -

This tutorial also builds on the introductory information provided in the -Building Your First App -tutorial, which explains how to set up your Eclipse environment -for building Android applications. We recommend you complete the Hello World -tutorial before starting this one.

- -

To prepare for this lesson:

- -
    -
  1. Download the project - exercises archive (.zip).
  2. -
  3. Unpack the archive file to a suitable location on your machine.
  4. -
  5. Open the NotepadCodeLab folder.
  6. -
- -

Inside the NotepadCodeLab folder, you should see six project -files: Notepadv1, - Notepadv2, Notepadv3, - Notepadv1Solution, Notepadv2Solution - and Notepadv3Solution. The Notepadv# projects are -the starting points for each of the exercises, while the -Notepadv#Solution projects are the exercise - solutions. If you are having trouble with a particular exercise, you - can compare your current work against the exercise solution.

- - -

Exercises

- -

The table below lists the tutorial exercises and describes the development -areas that each covers. Each exercise assumes that you have completed any -previous exercises.

- - - - - - - - - - - - - - - - - - -
Exercise -1Start here. Construct a simple notes list that lets the user add new notes but not -edit them. Demonstrates the basics of ListActivity and creating -and handling - menu options. Uses a SQLite database to store the notes.
Exercise 2Add a second Activity to the -application. Demonstrates constructing a -new Activity, adding it to the Android manifest, passing data between the -activities, and using more advanced screen layout. Also shows how to -invoke another Activity to return a result, using -startActivityForResult().
Exercise 3Add handling of life-cycle events to -the application, to let it -maintain application state across the life cycle.
Extra -CreditDemonstrates how to use the Eclipse -debugger and how you can use it to -view life-cycle events as they are generated. This section is optional but -highly recommended.
- - - -

Other Resources and Further Learning

-
    -
  • For a lighter but broader introduction to concepts not covered in the -tutorial, -take a look at Common Android Tasks.
  • - -
  • This tutorial draws from the full Notepad application included in the -samples/legacy/NotePad directory of the SDK, though it does not -match it exactly. When you are done with the tutorial, it is highly recommended -that you take a closer look at this version of the Notepad application, as it -demonstrates a variety of interesting additions for your application, such -as:
  • -
      -
    • Setting up a custom striped list for the list of notes.
    • -
    • Creating a custom text edit view that overrides the draw() - method to make it look like a lined notepad.
    • -
    • Implementing a full ContentProvider for notes.
    • -
    • Reverting and discarding edits instead of just automatically saving - them.
    • -
    -
diff --git a/docs/html/training/notepad/notepad-ex1.jd b/docs/html/training/notepad/notepad-ex1.jd deleted file mode 100644 index f680f1505d5f5..0000000000000 --- a/docs/html/training/notepad/notepad-ex1.jd +++ /dev/null @@ -1,583 +0,0 @@ -excludeFromSuggestions=true -page.title=Notepad Exercise 1 -parent.title=Notepad Tutorial -parent.link=index.html -@jd:body - - -

In this exercise, you will construct a simple notes list that lets the -user add new notes but not edit them. The exercise demonstrates:

-
    -
  • The basics of ListActivities and creating and handling menu -options.
  • -
  • How to use a SQLite database to store the notes.
  • -
  • How to bind data from a database cursor into a ListView using a -SimpleCursorAdapter.
  • -
  • The basics of screen layouts, including how to lay out a list view, how -you can add items to the activity menu, and how the activity handles those menu -selections.
  • -
- - - - - -

Step 1

- -

Open up the Notepadv1 project in Eclipse.

- -

Notepadv1 is a project that is provided as a starting point. It - takes care of some of the boilerplate work that you have already seen if you - followed the Hello, - World tutorial.

- -
    -
  1. - Start a new Android Project by clicking File > - New > Android Project.
  2. -
  3. - In the New Android Project dialog, select Create project from existing source.
  4. -
  5. - Click Browse and navigate to where you copied the NotepadCodeLab - (downloaded during setup) - and select Notepadv1.
  6. -
  7. - The Project Name and other properties should be automatically filled for you. - You must select the Build Target—we recommend selecting a target with the - lowest platform version available. Also add an integer to the Min SDK Version field - that matches the API Level of the selected Build Target.
  8. -
  9. - Click Finish. The Notepadv1 project should open and be - visible in your Eclipse package explorer.
  10. -
- -

If you see an error about AndroidManifest.xml, or some - problems related to an Android zip file, right click on the project and - select Android Tools > Fix Project Properties. - (The project is looking in the wrong location for the library file, - this will fix it for you.)

- -

Step 2

- - - -

Take a look at the NotesDbAdapter class — this class is provided to - encapsulate data access to a SQLite database that will hold our notes data - and allow us to update it.

-

At the top of the class are some constant definitions that will be used in the application - to look up data from the proper field names in the database. There is also a database creation - string defined, which is used to create a new database schema if one doesn't exist already.

-

Our database will have the name data, and have a single table called - notes, which in turn has three fields: _id, title and - body. The _id is named with an underscore convention used in a number of - places inside the Android SDK and helps keep a track of state. The _id - usually has to be specified when querying or updating the database (in the column projections - and so on). The other two fields are simple text fields that will store data. -

-

The constructor for NotesDbAdapter takes a Context, which allows it to communicate with aspects - of the Android operating system. This is quite common for classes that need to touch the - Android system in some way. The Activity class implements the Context class, so usually you will just pass - this from your Activity, when needing a Context.

-

The open() method calls up an instance of DatabaseHelper, which is our local - implementation of the SQLiteOpenHelper class. It calls getWritableDatabase(), - which handles creating/opening a database for us.

-

close() just closes the database, releasing resources related to the - connection.

-

createNote() takes strings for the title and body of a new note, - then creates that note in the database. Assuming the new note is created successfully, the - method also returns the row _id value for the newly created note.

-

deleteNote() takes a rowId for a particular note, and deletes that note from - the database.

- -

fetchAllNotes() issues a query to return a {@link android.database.Cursor} over all notes in the - database. The query() call is worth examination and understanding. The first field is the - name of the database table to query (in this case DATABASE_TABLE is "notes"). - The next is the list of columns we want returned, in this case we want the _id, - title and body columns so these are specified in the String array. - The remaining fields are, in order: selection, - selectionArgs, groupBy, having and orderBy. - Having these all null means we want all data, need no grouping, and will take the default - order. See {@link android.database.sqlite.SQLiteDatabase SQLiteDatabase} for more details.

-

Note: A Cursor is returned rather than a collection of rows. This allows - Android to use resources efficiently -- instead of putting lots of data straight into memory - the cursor will retrieve and release data as it is needed, which is much more efficient for - tables with lots of rows.

- -

fetchNote() is similar to fetchAllNotes() but just gets one note - with the rowId we specify. It uses a slightly different version of the - {@link android.database.sqlite.SQLiteDatabase} query() method. - The first parameter (set true) indicates that we are interested - in one distinct result. The selection parameter (the fourth parameter) has been specified to search - only for the row "where _id =" the rowId we passed in. So we are returned a Cursor on - the one row.

-

And finally, updateNote() takes a rowId, title and body, and uses a - {@link android.content.ContentValues ContentValues} instance to update the note of the given - rowId.

- -

Step 3

- - - -

Open the notepad_list.xml file in res/layout -and - take a look at it. (You may have to - hit the xml tab, at the bottom, in order to view the XML markup.)

- -

This is a mostly-empty layout definition file. Here are some - things you should know about a layout file:

- - -
    -
  • - All Android layout files must start with the XML header line: - <?xml version="1.0" encoding="utf-8"?>.
  • -
  • - The next definition will often (but not always) be a layout - definition of some kind, in this case a LinearLayout.
  • -
  • - The XML namespace of Android should always be defined in - the top level component or layout in the XML so that android: tags can - be used through the rest of the file: -

    xmlns:android="http://schemas.android.com/apk/res/android"

    -
  • -
- -

Step 4

-

We need to create the layout to hold our list. Add code inside - of the LinearLayout element so the whole file looks like this:

-
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content">
-
-  <ListView android:id="@android:id/list"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"/>
-  <TextView android:id="@android:id/empty"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/no_notes"/>
-
-</LinearLayout>
-
-
    -
  • - The @ symbol in the id strings of the ListView and - TextView tags means - that the XML parser should parse and expand the rest of - the id string and use an ID resource.
  • -
  • - The ListView and TextView can be - thought as two alternative views, only one of which will be displayed at once. - ListView will be used when there are notes to be shown, while the TextView - (which has a default value of "No Notes Yet!" defined as a string - resource in res/values/strings.xml) will be displayed if there - aren't any notes to display.
  • -
  • The list and empty IDs are - provided for us by the Android platform, so, we must - prefix the id with android: (e.g., @android:id/list).
  • -
  • The View with the empty id is used - automatically when the {@link android.widget.ListAdapter} has no data for the ListView. The - ListAdapter knows to look for this name by default. Alternatively, you could change the - default empty view by using {@link android.widget.AdapterView#setEmptyView(View)} - on the ListView. -

    - More broadly, the android.R class is a set of predefined - resources provided for you by the platform, while your project's - R class is the set of resources your project has defined. - Resources found in the android.R resource class can be - used in the XML files by using the android: name space prefix - (as we see here).

    -
  • -
- -

Step 5

- - - -

To make the list of notes in the ListView, we also need to define a View for each row:

-
    -
  1. - Create a new file under res/layout called - notes_row.xml.
  2. -
  3. - Add the following contents (note: again the XML header is used, and the - first node defines the Android XML namespace)
    -
    -<?xml version="1.0" encoding="utf-8"?>
    -<TextView android:id="@+id/text1"
    -    xmlns:android="http://schemas.android.com/apk/res/android"
    -    android:layout_width="wrap_content"
    -    android:layout_height="wrap_content"/>
    -

    - This is the View that will be used for each notes title row — it has only - one text field in it.

    -

    In this case we create a new id called text1. The - + after the @ in the id string indicates that the id should - be automatically created as a resource if it does not already exist, so we are defining - text1 on the fly and then using it.

    -
  4. -
  5. Save the file.
  6. -
-

Open the R.java class in the - project and look at it, you should see new definitions for - notes_row and text1 (our new definitions) - meaning we can now gain access to these from the our code.

- -

Step 6

-

Next, open the Notepadv1 class in the source. In the following steps, we are going to - alter this class to become a list adapter and display our notes, and also - allow us to add new notes.

- -

Notepadv1 will inherit from a subclass - of Activity called a ListActivity, - which has extra functionality to accommodate the kinds of - things you might want to do with a list, for - example: displaying an arbitrary number of list items in rows on the screen, - moving through the list items, and allowing them to be selected.

- -

Take a look through the existing code in Notepadv1 class. - There is a currently an unused private field called mNoteNumber that - we will use to create numbered note titles.

-

There are also three override methods defined: - onCreate, onCreateOptionsMenu and - onOptionsItemSelected; we need to fill these - out:

-
    -
  • onCreate() is called when the activity is - started — it is a little like the "main" method for an Activity. We use - this to set up resources and state for the activity when it is - running.
  • -
  • onCreateOptionsMenu() is used to populate the - menu for the Activity. This is shown when the user hits the menu button, -and - has a list of options they can select (like "Create - Note").
  • -
  • onOptionsItemSelected() is the other half of the - menu equation, it is used to handle events generated from the menu (e.g., - when the user selects the "Create Note" item). -
  • -
- -

Step 7

-

Change the inheritance of Notepadv1 from -Activity - to ListActivity:

-
public class Notepadv1 extends ListActivity
-

Note: you will have to import ListActivity into the -Notepadv1 - class using Eclipse, ctrl-shift-O on Windows or Linux, or - cmd-shift-O on the Mac (organize imports) will do this for you - after you've written the above change.

- -

Step 8

-

Fill out the body of the onCreate() method.

-

Here we will set the title for the Activity (shown at the top of the - screen), use the notepad_list layout we created in XML, - set up the NotesDbAdapter instance that will - access notes data, and populate the list with the available note - titles:

-
    -
  1. - In the onCreate method, call super.onCreate() with the - savedInstanceState parameter that's passed in.
  2. -
  3. - Call setContentView() and pass R.layout.notepad_list.
  4. -
  5. - At the top of the class, create a new private class field called mDbHelper of class - NotesDbAdapter. -
  6. -
  7. - Back in the onCreate method, construct a new -NotesDbAdapter - instance and assign it to the mDbHelper field (pass - this into the constructor for DBHelper) -
  8. -
  9. - Call the open() method on mDbHelper to open (or create) the - database. -
  10. -
  11. - Finally, call a new method fillData(), which will get the data and - populate the ListView using the helper — we haven't defined this method yet.
  12. -
-

- onCreate() should now look like this:

-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.notepad_list);
-        mDbHelper = new NotesDbAdapter(this);
-        mDbHelper.open();
-        fillData();
-    }
-

And be sure you have the mDbHelper field definition (right - under the mNoteNumber definition):

-
    private NotesDbAdapter mDbHelper;
- -

Step 9

- - - -

Fill out the body of the onCreateOptionsMenu() method.

- -

We will now create the "Add Item" button that can be accessed by pressing the menu -button on the device. We'll specify that it occupy the first position in the menu.

- -
    -
  1. - In strings.xml resource (under res/values), add - a new string named "menu_insert" with its value set to Add Item: -
    <string name="menu_insert">Add Item</string>
    -

    Then save the file and return to Notepadv1.

    -
  2. -
  3. Create a menu position constant at the top of the class: -
    public static final int INSERT_ID = Menu.FIRST;
    -
  4. -
  5. In the onCreateOptionsMenu() method, change the - super call so we capture the boolean return as result. We'll return this value at the end.
  6. -
  7. Then add the menu item with menu.add().
  8. -
-

The whole method should now look like this: -

-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        boolean result = super.onCreateOptionsMenu(menu);
-        menu.add(0, INSERT_ID, 0, R.string.menu_insert);
-        return result;
-    }
-

The arguments passed to add() indicate: a group identifier for this menu (none, - in this case), a unique ID (defined above), the order of the item (zero indicates no preference), - and the resource of the string to use for the item.

- -

Step 10

-

Fill out the body of the onOptionsItemSelected() method:

-

This is going - to handle our new "Add Note" menu item. When this is selected, the - onOptionsItemSelected() method will be called with the - item.getId() set to INSERT_ID (the constant we - used to identify the menu item). We can detect this, and take the - appropriate actions:

-
    -
  1. - The super.onOptionsItemSelected(item) method call goes at the - end of this method — we want to catch our events first!
  2. -
  3. - Write a switch statement on item.getItemId(). -

    In the case of INSERT_ID, call a new method, createNote(), - and return true, because we have handled this event and do not want to - propagate it through the system.

    -
  4. -
  5. Return the result of the superclass' onOptionsItemSelected() - method at the end.
  6. -
-

- The whole onOptionsItemSelect() method should now look like - this:

-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        switch (item.getItemId()) {
-        case INSERT_ID:
-            createNote();
-            return true;
-        }
-       
-        return super.onOptionsItemSelected(item);
-    }
- -

Step 11

-

Add a new createNote() method:

-

In this first version of - our application, createNote() is not going to be very useful. -We will simply - create a new note with a title assigned to it based on a counter ("Note 1", - "Note 2"...) and with an empty body. At present we have no way of editing - the contents of a note, so for now we will have to be content making one - with some default values:

-
    -
  1. Construct the name using "Note" and the counter we defined in the class: - String noteName = "Note " + mNoteNumber++
  2. -
  3. - Call mDbHelper.createNote() using noteName as the - title and "" for the body -
  4. -
  5. - Call fillData() to populate the list of notes (inefficient but - simple) — we'll create this method next.
  6. -
-

- The whole createNote() method should look like this:

-
-    private void createNote() {
-        String noteName = "Note " + mNoteNumber++;
-        mDbHelper.createNote(noteName, "");
-        fillData();
-    }
- - -

Step 12

- - -

Define the fillData() method:

-

This - method uses SimpleCursorAdapter, which takes a database Cursor - and binds it to fields provided in the layout. These fields define the row elements of our list - (in this case we use the text1 field in our - notes_row.xml layout), so this allows us to easily populate the list with - entries from our database.

-

To do this we have to provide a mapping from the title field in the returned Cursor, to - our text1 TextView, which is done by defining two arrays: the first a string array - with the list of columns to map from (just "title" in this case, from the constant - NotesDbAdapter.KEY_TITLE) and, the second, an int array - containing references to the views that we'll bind the data into - (the R.id.text1 TextView).

-

This is a bigger chunk of code, so let's first take a look at it:

- -
-    private void fillData() {
-        // Get all of the notes from the database and create the item list
-        Cursor c = mDbHelper.fetchAllNotes();
-        startManagingCursor(c);
-
-        String[] from = new String[] { NotesDbAdapter.KEY_TITLE };
-        int[] to = new int[] { R.id.text1 };
-        
-        // Now create an array adapter and set it to display using our row
-        SimpleCursorAdapter notes =
-            new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to);
-        setListAdapter(notes);
-    }
- -

Here's what we've done:

-
    -
  1. - After obtaining the Cursor from mDbHelper.fetchAllNotes(), we - use an Activity method called - startManagingCursor() that allows Android to take care of the - Cursor lifecycle instead of us needing to worry about it. (We will cover the implications - of the lifecycle in exercise 3, but for now just know that this allows Android to do some - of our resource management work for us.)
  2. -
  3. - Then we create a string array in which we declare the column(s) we want - (just the title, in this case), and an int array that defines the View(s) - to which we'd like to bind the columns (these should be in order, respective to - the string array, but here we only have one for each).
  4. -
  5. - Next is the SimpleCursorAdapter instantiation. - Like many classes in Android, the SimpleCursorAdapter needs a Context in order to do its - work, so we pass in this for the context (since subclasses of Activity - implement Context). We pass the notes_row View we created as the receptacle - for the data, the Cursor we just created, and then our arrays.
  6. -
-

- In the future, remember that the mapping between the from columns and to resources - is done using the respective ordering of the two arrays. If we had more columns we wanted - to bind, and more Views to bind them in to, we would specify them in order, for example we - might use { NotesDbAdapter.KEY_TITLE, NotesDbAdapter.KEY_BODY } and - { R.id.text1, R.id.text2 } to bind two fields into the row (and we would also need - to define text2 in the notes_row.xml, for the body text). This is how you can bind multiple fields - into a single row (and get a custom row layout as well).

-

- If you get compiler errors about classes not being found, ctrl-shift-O or - (cmd-shift-O on the mac) to organize imports. -

- -

Step 13

-

Run it! -

    -
  1. - Right click on the Notepadv1 project.
  2. -
  3. - From the popup menu, select Run As > - Android Application.
  4. -
  5. - If you see a dialog come up, select Android Launcher as the way of running - the application (you can also use the link near the top of the dialog to - set this as your default for the workspace; this is recommended as it will - stop the plugin from asking you this every time).
  6. -
  7. Add new notes by hitting the menu button and selecting Add - Item from the menu.
  8. -
- -

Solution and Next Steps

-

You can see the solution to this class in Notepadv1Solution -from -the zip file to compare with your own.

- -

Once you are ready, move on to Tutorial -Exercise 2 to add the ability to create, edit and delete notes.

- diff --git a/docs/html/training/notepad/notepad-ex2.jd b/docs/html/training/notepad/notepad-ex2.jd deleted file mode 100644 index 5ebd1aa966df4..0000000000000 --- a/docs/html/training/notepad/notepad-ex2.jd +++ /dev/null @@ -1,645 +0,0 @@ -excludeFromSuggestions=true -page.title=Notepad Exercise 2 -parent.title=Notepad Tutorial -parent.link=index.html -@jd:body - - -

In this exercise, you will add a second Activity to your notepad application, to let the user -create and edit notes. You will also allow the user to delete existing notes through a context menu. -The new Activity assumes responsibility for creating new notes by -collecting user input and packing it into a return Bundle provided by the intent. This exercise -demonstrates:

-
    -
  • Constructing a new Activity and adding it to the Android manifest
  • -
  • Invoking another Activity asynchronously using startActivityForResult()
  • -
  • Passing data between Activity in Bundle objects
  • -
  • How to use a more advanced screen layout
  • -
  • How to create a context menu
  • -
- - - -

Step 1

- -

Create a new Android project using the sources from Notepadv2 under the -NotepadCodeLab folder, just like you did for the first exercise. If you see an error about -AndroidManifest.xml, or some problems related to an -android.zip file, right click on the project and select Android -Tools > Fix Project Properties.

- -

Open the Notepadv2 project and take a look around:

-
    -
  • - Open and look at the strings.xml file under - res/values — there are several new strings which we will use - for our new functionality -
  • -
  • - Also, open and take a look at the top of the Notepadv2 class, - you will notice several new constants have been defined along with a new mNotesCursor - field used to hold the cursor we are using. -
  • -
  • - Note also that the fillData() method has a few more comments and now uses - the new field to store the notes Cursor. The onCreate() method is - unchanged from the first exercise. Also notice that the member field used to store the - notes Cursor is now called mNotesCursor. The m denotes a member - field and is part of the Android coding style standards. -
  • -
  • - There are also a couple of new overridden methods - (onCreateContextMenu(), onContextItemSelected(), - onListItemClick() and onActivityResult()) - which we will be filling in below. -
  • -
- - -

Step 2

- - -

First, let's create the context menu that will allow users to delete individual notes. -Open the Notepadv2 class.

- -
    -
  1. In order for each list item in the ListView to register for the context menu, we call - registerForContextMenu() and pass it our ListView. So, at the very end of - the onCreate() method add this line: -
    registerForContextMenu(getListView());
    -

    Because our Activity extends the ListActivity class, getListView() will return us - the local ListView object for the Activity. Now, each list item in this ListView will activate the - context menu. -

  2. - Now fill in the onCreateContextMenu() method. This callback is similar to the other - menu callback used for the options menu. Here, we add just one line, which will add a menu item - to delete a note. Call menu.add() like so: -
    -public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
    -    super.onCreateContextMenu(menu, v, menuInfo);
    -    menu.add(0, DELETE_ID, 0, R.string.menu_delete);
    -}
    -

    The onCreateContextMenu() callback passes some other information in addition to the Menu object, - such as the View that has been triggered for the menu and - an extra object that may contain additional information about the object selected. However, we don't care about - these here, because we only have one kind of object in the Activity that uses context menus. In the next - step, we'll handle the menu item selection.

    -
  3. -
- -

Step 3

-

Now that we've registered our ListView for a context menu and defined our context menu item, we need - to handle the callback when it is selected. For this, we need to identify the list ID of the - selected item, then delete it. So fill in the - onContextItemSelected() method like this:

-
-public boolean onContextItemSelected(MenuItem item) {
-    switch(item.getItemId()) {
-    case DELETE_ID:
-        AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
-        mDbHelper.deleteNote(info.id);
-        fillData();
-        return true;
-    }
-    return super.onContextItemSelected(item);
-}
-

Here, we retrieve the {@link android.widget.AdapterView.AdapterContextMenuInfo AdapterContextMenuInfo} -with {@link android.view.MenuItem#getMenuInfo()}. The id field of this object tells us -the position of the item in the ListView. We then pass this to the deleteNote() -method of our NotesDbAdapter and the note is deleted. That's it for the context menu — notes -can now be deleted.

- -

Step 4

- - -

Fill in the body of the createNote() method: -

Create a new Intent to create a note - (ACTIVITY_CREATE) using the NoteEdit class. - Then fire the Intent using the startActivityForResult() method - call:

-
-Intent i = new Intent(this, NoteEdit.class);
-startActivityForResult(i, ACTIVITY_CREATE);
-

This form of the Intent call targets a specific class in our Activity, in this case - NoteEdit. Since the Intent class will need to communicate with the Android - operating system to route requests, we also have to provide a Context (this).

-

The startActivityForResult() method fires the Intent in a way that causes a method - in our Activity to be called when the new Activity is completed. The method in our Activity - that receives the callback is called - onActivityResult() and we will implement it in a later step. The other way - to call an Activity is using startActivity() but this is a "fire-and-forget" way - of calling it — in this manner, our Activity is not informed when the Activity is completed, and there is - no way to return result information from the called Activity with startActivity(). -

Don't worry about the fact that NoteEdit doesn't exist yet, - we will fix that soon.

- - - -

Step 5

- -

Fill in the body of the onListItemClick() override.

-

onListItemClick() is a callback method that we'll override. It is called when - the user selects an item from the list. It is passed four parameters: the - ListView object it was invoked from, the View - inside the ListView that was clicked on, the - position in the list that was clicked, and the - mRowId of the item that was clicked. In this instance we can - ignore the first two parameters (we only have one ListView it - could be), and we ignore the mRowId as well. All we are - interested in is the position that the user selected. We use - this to get the data from the correct row, and bundle it up to send to - the NoteEdit Activity.

-

In our implementation of the callback, the method creates an - Intent to edit the note using - the NoteEdit class. It then adds data into the extras Bundle of - the Intent, which will be passed to the called Activity. We use it - to pass in the title and body text, and the mRowId for the note we are - editing. Finally, it will fire the Intent using the - startActivityForResult() method call. Here's the code that - belongs in onListItemClick():

-
-super.onListItemClick(l, v, position, id);
-Cursor c = mNotesCursor;
-c.moveToPosition(position);
-Intent i = new Intent(this, NoteEdit.class);
-i.putExtra(NotesDbAdapter.KEY_ROWID, id);
-i.putExtra(NotesDbAdapter.KEY_TITLE, c.getString(
-        c.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)));
-i.putExtra(NotesDbAdapter.KEY_BODY, c.getString(
-        c.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY)));
-startActivityForResult(i, ACTIVITY_EDIT);
-
    -
  • - putExtra() is the method to add items into the extras Bundle - to pass in to intent invocations. Here, we are - using the Bundle to pass in the title, body and mRowId of the note we want to edit. -
  • -
  • - The details of the note are pulled out from our query Cursor, which we move to the - proper position for the element that was selected in the list, with - the moveToPosition() method.
  • -
  • With the extras added to the Intent, we invoke the Intent on the - NoteEdit class by passing startActivityForResult() - the Intent and the request code. (The request code will be - returned to onActivityResult as the requestCode parameter.)
  • -
-

Note: We assign the mNotesCursor field to a local variable at the - start of the method. This is done as an optimization of the Android code. Accessing a local - variable is much more efficient than accessing a field in the Dalvik VM, so by doing this - we make only one access to the field, and five accesses to the local variable, making the - routine much more efficient. It is recommended that you use this optimization when possible.

- - -

Step 6

- -

The above createNote() and onListItemClick() - methods use an asynchronous Intent invocation. We need a handler for the callback, so here we fill - in the body of the onActivityResult().

-

onActivityResult() is the overridden method - which will be called when an Activity returns with a result. (Remember, an Activity - will only return a result if launched with startActivityForResult.) The parameters provided - to the callback are:

-
    -
  • requestCode — the original request code - specified in the Intent invocation (either ACTIVITY_CREATE or - ACTIVITY_EDIT for us). -
  • -
  • resultCode — the result (or error code) of the call, this - should be zero if everything was OK, but may have a non-zero code indicating - that something failed. There are standard result codes available, and you - can also create your own constants to indicate specific problems. -
  • -
  • intent — this is an Intent created by the Activity returning - results. It can be used to return data in the Intent "extras." -
  • -
-

The combination of startActivityForResult() and - onActivityResult() can be thought of as an asynchronous RPC - (remote procedure call) and forms the recommended way for an Activity to invoke - another and share services.

-

Here's the code that belongs in your onActivityResult():

-
-super.onActivityResult(requestCode, resultCode, intent);
-Bundle extras = intent.getExtras();
-
-switch(requestCode) {
-case ACTIVITY_CREATE:
-    String title = extras.getString(NotesDbAdapter.KEY_TITLE);
-    String body = extras.getString(NotesDbAdapter.KEY_BODY);
-    mDbHelper.createNote(title, body);
-    fillData();
-    break;
-case ACTIVITY_EDIT:
-    Long mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
-    if (mRowId != null) {
-        String editTitle = extras.getString(NotesDbAdapter.KEY_TITLE);
-        String editBody = extras.getString(NotesDbAdapter.KEY_BODY);
-        mDbHelper.updateNote(mRowId, editTitle, editBody);
-    }
-    fillData();
-    break;
-}
- -
    -
  • - We are handling both the ACTIVITY_CREATE and - ACTIVITY_EDIT activity results in this method. -
  • -
  • - In the case of a create, we pull the title and body from the extras (retrieved from the - returned Intent) and use them to create a new note. -
  • -
  • - In the case of an edit, we pull the mRowId as well, and use that to update - the note in the database. -
  • -
  • - fillData() at the end ensures everything is up to date . -
  • -
- - -

Step 7

- - - -

Open the file note_edit.xml that has been provided and take a - look at it. This is the UI code for the Note Editor.

-

This is the most - sophisticated UI we have dealt with yet. The file is given to you to avoid - problems that may sneak in when typing the code. (The XML is very strict - about case sensitivity and structure, mistakes in these are the usual cause - of problems with layout.)

-

There is a new parameter used - here that we haven't seen before: android:layout_weight (in - this case set to use the value 1 in each case).

-

layout_weight is used in LinearLayouts - to assign "importance" to Views within the layout. All Views have a default - layout_weight of zero, meaning they take up only as much room - on the screen as they need to be displayed. Assigning a value higher than - zero will split up the rest of the available space in the parent View, according - to the value of each View's layout_weight and its ratio to the - overall layout_weight specified in the current layout for this - and other View elements.

-

To give an example: let's say we have a text label - and two text edit elements in a horizontal row. The label has no - layout_weight specified, so it takes up the minimum space - required to render. If the layout_weight of each of the two - text edit elements is set to 1, the remaining width in the parent layout will - be split equally between them (because we claim they are equally important). - If the first one has a layout_weight of 1 - and the second has a layout_weight of 2, then one third of the - remaining space will be given to the first, and two thirds to the - second (because we claim the second one is more important).

-

This layout also demonstrates how to nest multiple layouts - inside each other to achieve a more complex and pleasant layout. In this - example, a horizontal linear layout is nested inside the vertical one to - allow the title label and text field to be alongside each other, - horizontally.

- - -

Step 8

- -

Create a NoteEdit class that extends - android.app.Activity.

-

This is the first time we will have - created an Activity without the Android Eclipse plugin doing it for us. When - you do so, the onCreate() method is not automatically - overridden for you. It is hard to imagine an Activity that doesn't override - the onCreate() method, so this should be the first thing you do.

-
    -
  1. Right click on the com.android.demo.notepad2 package - in the Package Explorer, and select New > Class from the popup - menu.
  2. -
  3. Fill in NoteEdit for the Name: field in the - dialog.
  4. -
  5. In the Superclass: field, enter - android.app.Activity (you can also just type Activity and hit - Ctrl-Space on Windows and Linux or Cmd-Space on the Mac, to invoke code - assist and find the right package and class).
  6. -
  7. Click Finish.
  8. -
  9. In the resulting NoteEdit class, right click in the editor - window and select Source > Override/Implement Methods...
  10. -
  11. Scroll down through the checklist in the dialog until you see - onCreate(Bundle) — and check the box next to it.
  12. -
  13. Click OK.

    The method should now appear in your class.

  14. -
- -

Step 9

- -

Fill in the body of the onCreate() method for NoteEdit.

- -

This will set the title of our new Activity to say "Edit Note" (one - of the strings defined in strings.xml). It will also set the - content view to use our note_edit.xml layout file. We can then - grab handles to the title and body text edit views, and the confirm button, - so that our class can use them to set and get the note title and body, - and attach an event to the confirm button for when it is pressed by the - user.

-

We can then unbundle the values that were passed in to the Activity - with the extras Bundle attached to the calling Intent. We'll use them to pre-populate - the title and body text edit views so that the user can edit them. - Then we will grab and store the mRowId so we can keep - track of what note the user is editing.

- -
    -
  1. - Inside onCreate(), set up the layout:
    -
    setContentView(R.layout.note_edit);
    -
  2. -
  3. - Change the Activity title to the "Edit Note" string: -
    setTitle(R.string.edit_note);
    -
  4. -
  5. - Find the {@link android.widget.EditText} and {@link android.widget.Button} components we need: -

    These are found by the - IDs associated to them in the R class, and need to be cast to the right - type of View (EditText for the two text views, - and Button for the confirm button):

    -
    -mTitleText = (EditText) findViewById(R.id.title);
    -mBodyText = (EditText) findViewById(R.id.body);
    -Button confirmButton = (Button) findViewById(R.id.confirm);
    -

    Note that mTitleText and mBodyText are member - fields (you need to declare them at the top of the class definition).

    -
  6. -
  7. At the top of the class, declare a Long mRowId private field to store - the current mRowId being edited (if any). -
  8. -
  9. Continuing inside onCreate(), - add code to initialize the title, body and - mRowId from the extras Bundle in - the Intent (if it is present):
    -
    -mRowId = null;
    -Bundle extras = getIntent().getExtras();
    -if (extras != null) {
    -    String title = extras.getString(NotesDbAdapter.KEY_TITLE);
    -    String body = extras.getString(NotesDbAdapter.KEY_BODY);
    -    mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
    -
    -    if (title != null) {
    -        mTitleText.setText(title);
    -    }
    -    if (body != null) {
    -        mBodyText.setText(body);
    -    }
    -}
    -
      -
    • - We are pulling the title and - body out of the - extras Bundle that was set from the - Intent invocation. -
    • - We also null-protect the text field setting (i.e., we don't want to set - the text fields to null accidentally).
    • -
    -
  10. -
  11. - Create an onClickListener() for the button: -

    Listeners can be one of the more confusing aspects of UI - implementation, but - what we are trying to achieve in this case is simple. We want an - onClick() method to be called when the user presses the - confirm button, and use that to do some work and return the values - of the edited note to the Intent caller. We do this using something called - an anonymous inner class. This is a bit confusing to look at unless you - have seen them before, but all you really need to take away from this is - that you can refer to this code in the future to see how to create a - listener and attach it to a button. (Listeners are a common idiom - in Java development, particularly for user interfaces.) Here's the empty listener:
    -

    -confirmButton.setOnClickListener(new View.OnClickListener() {
    -
    -    public void onClick(View view) {
    -
    -    }
    -
    -});
    -
  12. -
-

Step 10

- -

Fill in the body of the onClick() method of the OnClickListener created in the last step.

- -

This is the code that will be run when the user clicks on the - confirm button. We want this to grab the title and body text from the edit - text fields, and put them into the return Bundle so that they can be passed - back to the Activity that invoked this NoteEdit Activity. If the - operation is an edit rather than a create, we also want to put the - mRowId into the Bundle so that the - Notepadv2 class can save the changes back to the correct - note.

-
    -
  1. - Create a Bundle and put the title and body text into it using the - constants defined in Notepadv2 as keys:
    -
    -Bundle bundle = new Bundle();
    -
    -bundle.putString(NotesDbAdapter.KEY_TITLE, mTitleText.getText().toString());
    -bundle.putString(NotesDbAdapter.KEY_BODY, mBodyText.getText().toString());
    -if (mRowId != null) {
    -    bundle.putLong(NotesDbAdapter.KEY_ROWID, mRowId);
    -}
    -
  2. -
  3. - Set the result information (the Bundle) in a new Intent and finish the Activity: -
    -Intent mIntent = new Intent();
    -mIntent.putExtras(bundle);
    -setResult(RESULT_OK, mIntent);
    -finish();
    -
      -
    • The Intent is simply our data carrier that carries our Bundle - (with the title, body and mRowId).
    • -
    • The setResult() method is used to set the result - code and return Intent to be passed back to the - Intent caller. In this case everything worked, so we return RESULT_OK for the - result code.
    • -
    • The finish() call is used to signal that the Activity - is done (like a return call). Anything set in the Result will then be - returned to the caller, along with execution control.
    • -
    -
  4. -
-

The full onCreate() method (plus supporting class fields) should - now look like this:

-
-private EditText mTitleText;
-private EditText mBodyText;
-private Long mRowId;
-
-@Override
-protected void onCreate(Bundle savedInstanceState) {
-    super.onCreate(savedInstanceState);
-    setContentView(R.layout.note_edit);
-
-    mTitleText = (EditText) findViewById(R.id.title);
-    mBodyText = (EditText) findViewById(R.id.body);
-
-    Button confirmButton = (Button) findViewById(R.id.confirm);
-
-    mRowId = null;
-    Bundle extras = getIntent().getExtras();
-    if (extras != null) {
-        String title = extras.getString(NotesDbAdapter.KEY_TITLE);
-        String body = extras.getString(NotesDbAdapter.KEY_BODY);
-        mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
-
-        if (title != null) {
-            mTitleText.setText(title);
-        }
-        if (body != null) {
-            mBodyText.setText(body);
-        }
-    }
-
-    confirmButton.setOnClickListener(new View.OnClickListener() {
-
-        public void onClick(View view) {
-            Bundle bundle = new Bundle();
-
-            bundle.putString(NotesDbAdapter.KEY_TITLE, mTitleText.getText().toString());
-            bundle.putString(NotesDbAdapter.KEY_BODY, mBodyText.getText().toString());
-            if (mRowId != null) {
-                bundle.putLong(NotesDbAdapter.KEY_ROWID, mRowId);
-            }
-
-            Intent mIntent = new Intent();
-            mIntent.putExtras(bundle);
-            setResult(RESULT_OK, mIntent);
-            finish();
-        }
-    });
-}
- - - -

Step 11

- - - -

Finally, the new Activity has to be defined in the manifest file:

-

Before the new Activity can be seen by Android, it needs its own - Activity entry in the AndroidManifest.xml file. This is to let - the system know that it is there and can be called. We could also specify - which IntentFilters the activity implements here, but we are going to skip - this for now and just let Android know that the Activity is - defined.

-

There is a Manifest editor included in the Eclipse plugin that makes it much easier - to edit the AndroidManifest file, and we will use this. If you prefer to edit the file directly - or are not using the Eclipse plugin, see the box at the end for information on how to do this - without using the new Manifest editor.

-

    -
  1. Double click on the AndroidManifest.xml file in the package explorer to open it. -
  2. -
  3. Click the Application tab at the bottom of the Manifest editor.
  4. -
  5. Click Add... in the Application Nodes section. -

    If you see a dialog with radiobuttons at the top, select the top radio button: - "Create a new element at the top level, in Application".

  6. -
  7. Make sure "(A) Activity" is selected in the selection pane of the dialog, and click OK.
  8. -
  9. Click on the new "Activity" node, in the Application Nodes section, then - type .NoteEdit into the Name* - field to the right. Press Return/Enter.
  10. -
-

The Android Manifest editor helps you add more complex entries into the AndroidManifest.xml - file, have a look around at some of the other options available (but be careful not to select - them otherwise they will be added to your Manifest). This editor should help you understand - and alter the AndroidManifest.xml file as you move on to more advanced Android applications.

- -

If you prefer to edit this file directly, simply open the - AndroidManifest.xml file and look at the source (use the - AndroidManifest.xml tab in the eclipse editor to see the source code directly). - Then edit the file as follows:
- <activity android:name=".NoteEdit" />

- This should be placed just below the line that reads:
- </activity> for the .Notepadv2 activity.

- -

Step 12

- -

Now Run it!

-

You should now be able to add real notes from -the menu, as well as delete an existing one. Notice that in order to delete, you must -first use the directional controls on the device to highlight the note. -Furthermore, selecting a note title from the list should bring up the note -editor to let you edit it. Press confirm when finished to save the changes -back to the database. - -

Solution and Next Steps

- -

You can see the solution to this exercise in Notepadv2Solution -from the zip file to compare with your own.

-

Now try editing a note, and then hitting the back button on the emulator -instead of the confirm button (the back button is below the menu button). You -will see an error come up. Clearly our application still has some problems. -Worse still, if you did make some changes and hit the back button, when you go -back into the notepad to look at the note you changed, you will find that all -your changes have been lost. In the next exercise we will fix these -problems.

- -

-Once you are ready, move on to Tutorial -Exercise 3 where you will fix the problems with the back button and lost -edits by introducing a proper life cycle into the NoteEdit Activity.

- - diff --git a/docs/html/training/notepad/notepad-ex3.jd b/docs/html/training/notepad/notepad-ex3.jd deleted file mode 100644 index 648f9f2d9bb74..0000000000000 --- a/docs/html/training/notepad/notepad-ex3.jd +++ /dev/null @@ -1,367 +0,0 @@ -excludeFromSuggestions=true -page.title=Notepad Exercise 3 -parent.title=Notepad Tutorial -parent.link=index.html -@jd:body - - -

In this exercise, you will use life-cycle event callbacks to store and -retrieve application state data. This exercise demonstrates:

-
    -
  • Life-cycle events and how your application can use them
  • -
  • Techniques for maintaining application state
  • -
- - - -

Step 1

- -

Import Notepadv3 into Eclipse. If you see an error about -AndroidManifest.xml, or some problems related to an Android zip -file, right click on the project and select Android Tools > -Fix Project Properties from the popup menu. The starting point for this exercise is -exactly where we left off at the end of the Notepadv2.

-

The current application has some problems — hitting the back button when editing -causes a crash, and anything else that happens during editing will cause the -edits to be lost.

-

To fix this, we will move most of the functionality for creating and editing -the note into the NoteEdit class, and introduce a full life cycle for editing -notes.

- -
    -
  1. Remove the code in NoteEdit that parses the title and body - from the extras Bundle. -

    Instead, we are going to use the DBHelper class - to access the notes from the database directly. All we need passed into the - NoteEdit Activity is a mRowId (but only if we are editing, if creating we pass - nothing). Remove these lines:

    -
    -String title = extras.getString(NotesDbAdapter.KEY_TITLE);
    -String body = extras.getString(NotesDbAdapter.KEY_BODY);
    -
  2. -
  3. We will also get rid of the properties that were being passed in - the extras Bundle, which we were using to set the title - and body text edit values in the UI. So delete: -
    -if (title != null) {
    -    mTitleText.setText(title);
    -}
    -if (body != null) {
    -    mBodyText.setText(body);
    -}
    -
  4. -
- -

Step 2

- -

Create a class field for a NotesDbAdapter at the top of the NoteEdit class:

-
    private NotesDbAdapter mDbHelper;
-

Also add an instance of NotesDbAdapter in the - onCreate() method (right below the super.onCreate() call):

-
-    mDbHelper = new NotesDbAdapter(this);
-    mDbHelper.open();
- -

Step 3

- -

In NoteEdit, we need to check the savedInstanceState for the -mRowId, in case the note - editing contains a saved state in the Bundle, which we should recover (this would happen - if our Activity lost focus and then restarted).

-
    -
  1. - Replace the code that currently initializes the mRowId:
    -
    -        mRowId = null;
    -
    -        Bundle extras = getIntent().getExtras();
    -        if (extras != null) {
    -            mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
    -        }
    -        
    - with this: -
    -        mRowId = (savedInstanceState == null) ? null :
    -            (Long) savedInstanceState.getSerializable(NotesDbAdapter.KEY_ROWID);
    -        if (mRowId == null) {
    -            Bundle extras = getIntent().getExtras();
    -            mRowId = extras != null ? extras.getLong(NotesDbAdapter.KEY_ROWID)
    -                                    : null;
    -        }
    -        
    -
  2. -
  3. - Note the null check for savedInstanceState, and we still need to load up - mRowId from the extras Bundle if it is not - provided by the savedInstanceState. This is a ternary operator shorthand - to safely either use the value or null if it is not present. -
  4. -
  5. - Note the use of Bundle.getSerializable() instead of - Bundle.getLong(). The latter encoding returns a long primitive and - so can not be used to represent the case when mRowId is null. -
  6. -
- -

Step 4

- -

Next, we need to populate the fields based on the mRowId if we - have it:

-
populateFields();
-

This goes before the confirmButton.setOnClickListener() line. - We'll define this method in a moment.

- -

Step 5

- -

Get rid of the Bundle creation and Bundle value settings from the - onClick() handler method. The Activity no longer needs to - return any extra information to the caller. And because we no longer have - an Intent to return, we'll use the shorter version - of setResult():

-
-public void onClick(View view) {
-    setResult(RESULT_OK);
-    finish();
-}
-

We will take care of storing the updates or new notes in the database - ourselves, using the life-cycle methods.

- -

The whole onCreate() method should now look like this:

-
-super.onCreate(savedInstanceState);
-
-mDbHelper = new NotesDbAdapter(this);
-mDbHelper.open();
-
-setContentView(R.layout.note_edit);
-
-mTitleText = (EditText) findViewById(R.id.title);
-mBodyText = (EditText) findViewById(R.id.body);
-
-Button confirmButton = (Button) findViewById(R.id.confirm);
-
-mRowId = (savedInstanceState == null) ? null :
-    (Long) savedInstanceState.getSerializable(NotesDbAdapter.KEY_ROWID);
-if (mRowId == null) {
-    Bundle extras = getIntent().getExtras();
-    mRowId = extras != null ? extras.getLong(NotesDbAdapter.KEY_ROWID)
-                            : null;
-}
-
-populateFields();
-
-confirmButton.setOnClickListener(new View.OnClickListener() {
-
-    public void onClick(View view) {
-        setResult(RESULT_OK);
-        finish();
-    }
-
-});
- -

Step 6

- -

Define the populateFields() method.

-
-private void populateFields() {
-    if (mRowId != null) {
-        Cursor note = mDbHelper.fetchNote(mRowId);
-        startManagingCursor(note);
-        mTitleText.setText(note.getString(
-	            note.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)));
-        mBodyText.setText(note.getString(
-                note.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY)));
-    }
-}
-

This method uses the NotesDbAdapter.fetchNote() method to find the right note to -edit, then it calls startManagingCursor() from the Activity class, which -is an Android convenience method provided to take care of the Cursor life-cycle. This will release -and re-create resources as dictated by the Activity life-cycle, so we don't need to worry about -doing that ourselves. After that, we just look up the title and body values from the Cursor -and populate the View elements with them.

- - -

Step 7

- - - -

Still in the NoteEdit class, we now override the methods - onSaveInstanceState(), onPause() and - onResume(). These are our life-cycle methods - (along with onCreate() which we already have).

- -

onSaveInstanceState() is called by Android if the - Activity is being stopped and may be killed before it is - resumed! This means it should store any state necessary to - re-initialize to the same condition when the Activity is restarted. It is - the counterpart to the onCreate() method, and in fact the - savedInstanceState Bundle passed in to onCreate() is the same - Bundle that you construct as outState in the - onSaveInstanceState() method.

- -

onPause() and onResume() are also - complimentary methods. onPause() is always called when the - Activity ends, even if we instigated that (with a finish() call for example). - We will use this to save the current note back to the database. Good - practice is to release any resources that can be released during an - onPause() as well, to take up less resources when in the - passive state. onResume() will call our populateFields() method - to read the note out of the database again and populate the fields.

- -

So, add some space after the populateFields() method - and add the following life-cycle methods:

-
    -
  1. - onSaveInstanceState(): -
    -    @Override
    -    protected void onSaveInstanceState(Bundle outState) {
    -        super.onSaveInstanceState(outState);
    -        saveState();
    -        outState.putSerializable(NotesDbAdapter.KEY_ROWID, mRowId);
    -    }
    -

    We'll define saveState() next.

    -
  2. -
  3. - onPause(): -
    -    @Override
    -    protected void onPause() {
    -        super.onPause();
    -        saveState();
    -    }
    -
  4. -
  5. - onResume(): -
    -    @Override
    -    protected void onResume() {
    -        super.onResume();
    -        populateFields();
    -    }
    -
  6. -
-

Note that saveState() must be called in both onSaveInstanceState() -and onPause() to ensure that the data is saved. This is because there is no -guarantee that onSaveInstanceState() will be called and because when it is -called, it is called before onPause().

- - -

Step 8

- -

Define the saveState() method to put the data out to the -database.

-
-     private void saveState() {
-        String title = mTitleText.getText().toString();
-        String body = mBodyText.getText().toString();
-
-        if (mRowId == null) {
-            long id = mDbHelper.createNote(title, body);
-            if (id > 0) {
-                mRowId = id;
-            }
-        } else {
-            mDbHelper.updateNote(mRowId, title, body);
-        }
-    }
-

Note that we capture the return value from createNote() and if a valid row ID is - returned, we store it in the mRowId field so that we can update the note in future - rather than create a new one (which otherwise might happen if the life-cycle events are - triggered).

- - -

Step 9

- -

Now pull out the previous handling code from the - onActivityResult() method in the Notepadv3 - class.

-

All of the note retrieval and updating now happens within the - NoteEdit life cycle, so all the onActivityResult() - method needs to do is update its view of the data, no other work is - necessary. The resulting method should look like this:

-
-@Override
-protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
-    super.onActivityResult(requestCode, resultCode, intent);
-    fillData();
-}
- -

Because the other class now does the work, all this has to do is refresh - the data.

- -

Step 10

- -

Also remove the lines which set the title and body from the - onListItemClick() method (again they are no longer needed, - only the mRowId is):

-
-    Cursor c = mNotesCursor;
-    c.moveToPosition(position);
-
-and also remove: -
-
-    i.putExtra(NotesDbAdapter.KEY_TITLE, c.getString(
-                    c.getColumnIndex(NotesDbAdapter.KEY_TITLE)));
-    i.putExtra(NotesDbAdapter.KEY_BODY, c.getString(
-                    c.getColumnIndex(NotesDbAdapter.KEY_BODY)));
-
-so that all that should be left in that method is: -
-
-    super.onListItemClick(l, v, position, id);
-    Intent i = new Intent(this, NoteEdit.class);
-    i.putExtra(NotesDbAdapter.KEY_ROWID, id);
-    startActivityForResult(i, ACTIVITY_EDIT);
- -

You can also now remove the mNotesCursor field from the class, and set it back to using - a local variable in the fillData() method: -

-    Cursor notesCursor = mDbHelper.fetchAllNotes();

-

Note that the m in mNotesCursor denotes a member field, so when we - make notesCursor a local variable, we drop the m. Remember to rename the - other occurrences of mNotesCursor in your fillData() method. - -

-Run it! (use Run As -> Android Application on the project right -click menu again)

- -

Solution and Next Steps

- -

You can see the solution to this exercise in Notepadv3Solution -from -the zip file to compare with your own.

-

-When you are ready, move on to the Tutorial -Extra Credit exercise, where you can use the Eclipse debugger to -examine the life-cycle events as they happen.

diff --git a/docs/html/training/notepad/notepad-extra-credit.jd b/docs/html/training/notepad/notepad-extra-credit.jd deleted file mode 100644 index 8ab20218788c5..0000000000000 --- a/docs/html/training/notepad/notepad-extra-credit.jd +++ /dev/null @@ -1,71 +0,0 @@ -excludeFromSuggestions=true -page.title=Notepad Extra Credit -parent.title=Notepad Tutorial -parent.link=index.html -@jd:body - - -

In this exercise, you will use the debugger to look at the work you did -in Exercise 3. This exercise demonstrates:

-
    -
  • How to set breakpoints to observe execution
  • -
  • How to run your application in debug mode
  • -
- -
- - [Exercise 1] - [Exercise 2] - [Exercise 3] - - [Extra Credit] - -
- -

Step 1

- -

Using the working Notepadv3, put breakpoints in the code at the - beginning of the onCreate(), onPause(), - onSaveInstanceState() and onResume() methods in the - NoteEdit class (if you are not familiar with Eclipse, just - right click in the narrow grey border on the left of the edit window at the - line you want a breakpoint, and select Toggle Breakpoint, you -should see a blue dot appear).

- -

Step 2

- -

Now start the notepad demo in debug mode:

- -
    -
  1. - Right click on the Notepadv3 project and from the Debug menu - select Debug As -> Android Application.
  2. -
  3. - The Android emulator should say "waiting for debugger to connect" - briefly and then run the application.
  4. -
  5. - If it gets stuck on the waiting... screen, quit the emulator and Eclipse, - from the command line do an adb kill-server, and then restart -Eclipse and try again.
- -

Step 3

- -

When you edit or create a new note you should see the breakpoints getting - hit and the execution stopping.

- -

Step 4

- -

Hit the Resume button to let execution continue (yellow rectangle with a -green triangle to its right in the Eclipse toolbars near the top).

- -

Step 5

- -

Experiment a bit with the confirm and back buttons, and try pressing Home and - making other mode changes. Watch what life-cycle events are generated and -when.

- -

The Android Eclipse plugin not only offers excellent debugging support for -your application development, but also superb profiling support. You can also -try using Traceview to profile your application. If your application is running too slow, this can help you -find the bottlenecks and fix them.

- diff --git a/docs/html/training/notepad/notepad-index.jd b/docs/html/training/notepad/notepad-index.jd deleted file mode 100644 index fde43fa7db268..0000000000000 --- a/docs/html/training/notepad/notepad-index.jd +++ /dev/null @@ -1,144 +0,0 @@ -excludeFromSuggestions=true -page.title=Notepad Tutorial -@jd:body - - -

The tutorial in this section gives you a "hands-on" introduction -to the Android framework and the tools you use to build applications on it. -Starting from a preconfigured project file, it guides you through the process of -developing a simple notepad application and provides concrete examples of how to -set up the project, develop the application logic and user interface, and then -compile and run the application.

- -

The tutorial presents the notepad application development as a set of -exercises (see below), each consisting of several steps. You can follow along -with the steps in each exercise and gradually build up and refine your -application. The exercises explain each step in detail and provide all the -sample code you need to complete the application.

- -

When you are finished with the tutorial, you will have created a functioning -Android application and learned in depth about many of the most important -concepts in Android development. If you want to add more complex features to -your application, you can examine the code in an alternative implementation -of a notepad application, in the -Sample Code documentation.

- - - -

Who Should Use this Tutorial

- -

This tutorial is designed for experienced developers, especially those with -knowledge of the Java programming language. If you haven't written Java -applications before, you can still use the tutorial, but you might need to work -at a slower pace.

- -

The tutorial assumes that you have some familiarity with the basic Android -application concepts and terminology. If you aren't yet familiar with those, you -should read Overview of an Android -Application before continuing.

- -

Also note that this tutorial uses -the Eclipse development environment, with the Android plugin installed. If you -are not using Eclipse, you can follow the exercises and build the application, -but you will need to determine how to accomplish the Eclipse-specific -steps in your environment.

- - -

Preparing for the Exercises

- -

This tutorial builds on the information provided in the Installing the SDK and Hello Android -documents, which explain in detail how to set up your development environment -for building Android applications. Before you start this tutorial, you should -read both these documents, have the SDK installed, and your work environment set up.

- -

To prepare for this lesson:

- -
    -
  1. Download the project - exercises archive (.zip)
  2. -
  3. Unpack the archive file to a suitable location on your machine
  4. -
  5. Open the NotepadCodeLab folder
  6. -
- -

Inside the NotepadCodeLab folder, you should see six project -files: Notepadv1, - Notepadv2, Notepadv3, - Notepadv1Solution, Notepadv2Solution - and Notepadv3Solution. The Notepadv# projects are -the starting points for each of the exercises, while the -Notepadv#Solution projects are the exercise - solutions. If you are having trouble with a particular exercise, you - can compare your current work against the exercise solution.

- - -

Exercises

- -

The table below lists the tutorial exercises and describes the development -areas that each covers. Each exercise assumes that you have completed any -previous exercises.

- - - - - - - - - - - - - - - - - - -
Exercise -1Start here. Construct a simple notes list that lets the user add new notes but not -edit them. Demonstrates the basics of ListActivity and creating -and handling - menu options. Uses a SQLite database to store the notes.
Exercise 2Add a second Activity to the -application. Demonstrates constructing a -new Activity, adding it to the Android manifest, passing data between the -activities, and using more advanced screen layout. Also shows how to -invoke another Activity to return a result, using -startActivityForResult().
Exercise 3Add handling of life-cycle events to -the application, to let it -maintain application state across the life cycle.
Extra -CreditDemonstrates how to use the Eclipse -debugger and how you can use it to -view life-cycle events as they are generated. This section is optional but -highly recommended.
- - - -

Other Resources and Further Learning

-
    -
  • For a lighter but broader introduction to concepts not covered in the -tutorial, -take a look at Common Android Tasks.
  • -
  • The Android SDK includes a variety of fully functioning sample applications -that make excellent opportunities for further learning. You can find the sample -applications in the samples/ directory of your downloaded SDK.
  • -
  • This tutorial draws from the full Notepad application included in the -samples/ directory of the SDK, though it does not match it exactly. -When you are done with the tutorial, -it is highly recommended that you take a closer look at this version of the Notepad -application, -as it demonstrates a variety of interesting additions for your application, -such as:
  • -
      -
    • Setting up a custom striped list for the list of notes.
    • -
    • Creating a custom text edit view that overrides the draw() -method to - make it look like a lined notepad.
    • -
    • Implementing a full ContentProvider for notes.
    • -
    • Reverting and discarding edits instead of just automatically saving -them.
    • -
    -