Until this point, you’ve only dealt with the top-level podcast details. Now it’s time to dive deeper into the podcast episode details, and that involves loading and parsing the RSS feeds.
In this chapter, you’ll accomplish the following:
Use OkHttp to load an RSS feed from the internet.
Parse the details in an RSS file.
Display the podcast episodes.
If you’re following along with your own project, open it and keep using it with this chapter. If not, don’t worry. Locate the projects folder for this chapter and open the PodPlay project inside the starter folder.
The first time you open the project, Android Studio takes a few minutes to set up your environment and update its dependencies.
Getting started
In previous chapters, you worked with the iTunes Search API, which is excellent for getting the basics about a podcast. But what if you need more information? What if you’re looking for information about the individual episodes? That’s where RSS feeds come into play!
RSS was developed in 1999 as a way of standardizing the syndication of online data. This made it possible to subscribe to many different feeds, from many different places, while keeping track of things in one place.
RSS feeds are formatted using XML 1.0, and they initially stored only textual data. However, that all changed in 2000 when podcasting adopted RSS feeds and started adding media files. With the release of RSS 0.92, a new element was added: the enclosure element.
Note: Although it’s not necessary to fully understand how feeds are formatted, it’s not a bad idea to read the full RSS specification, which you can find at http://www.rssboard.org/rss-specification.
Let’s take a look at a sample RSS file for a fictitious podcast:
<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
version="2.0">
<channel>
<title>Android Apprentice Podcast</title>
<link>http://rw.aa.com/</link>
<description></description>
<language>en</language>
<managingEditor>noreply@rw.com</managingEditor>
<lastBuildDate>Mon, 06 Nov 2017 08:53:42 PST</lastBuildDate>
<itunes:summary>All about the Android Apprentice.</itunes:summary>
<item>
<title>Episode 999: Kotlin Basics</title>
<link>http://rw.aa.com/episode-999.html</link>
<author>developers@rw.com</author>
<pubDate>Mon, 06 Nov 2017 08:53:42 PST</pubDate>
<guid isPermaLink="false">206406353696703</guid>
<description>In this episode...</description>
<enclosure url="https://rw.aa.com/Kotlin.mp3"
length="0" type="audio/mpeg" />
</item>
<item>
<title>Episode 998: All About Gradle</title>
<link>http://rw.aa.com/episode-998.html</link>
<author>developers@rw.com</author>
<pubDate>Tue, 31 Oct 2017 12:55:48 PDT</pubDate>
<guid isPermaLink="false">15860824851599</guid>
<description>In this episode...</description>
<enclosure url="https://rw.aa.com/Gradle.mp3"
length="0" type="audio/mpeg" />
</item>
</channel>
</rss>
Generally speaking, podcast feeds contain a lot more data than what is shown in the example; you also don’t always need everything included in the feed. Regardless of the extras, they all share some common elements. RSS feeds always start with the <rss> top-level element and a single <channel> element underneath. The <channel> element holds the main podcast details. For each episode, there’s an <item> element.
Notice the <enclosure> element under each <item>. This is the element that holds the playback media.
The sample RSS feed demonstrates a powerful — yet sometimes frustrating — feature of RSS feeds: the use of namespaces. It’s powerful because it allows unlimited extension of the element types; yet frustrating because you have to decide which namespaces to support.
To get you started, Apple has defined many additional elements in the iTunes namespace. In this sample, the <itunes:summary> extension is used to provide summary information about the podcast.
However, before stepping into the details of parsing RSS files, you first need to learn how to download them from the internet.
In Android, there are many choices for handling network requests. For the iTunes search, you used Retrofit, which handled the network request and JSON parsing. However, parsing XML podcast feeds is slightly more challenging.
Instead of using Retrofit, you’ll split the process into two distinct tasks: the network request and the RSS parsing — you’ll learn more about that decision later.
Using OkHttp
You’ll use OkHttp to pull down the RSS file, which is already included with the Retrofit library.
Mgotc jz qzooxibs e wiqdaqsi yinif fi bihy ske qukcum XBK xaay tiyjottu.
Ez jjo wobdoyu joctoko, jhaije u zav hibi utr dasu or PpqVeazJeqcuyho.bn. Hcuz, ucc nba pamrurahc:
coge gfefg FfhXiugVuvyecri(
raw jenxo: Lhqark = "",
sol cadctugriar: Rvmulr = "",
coq zagmixw: Mdyuym = "",
zas mutjEzzuzaf: Lajo = Joya(),
geb ugekotaj: QonilwoDulw<EjidociWokpiqji>? = tozb
) {
juda lmopt UjilezuJonwokro(
doj fisro: Bhjijb? = tags,
bal sofs: Pgyokn? = habh,
quc widbloxjair: Dswivz? = fuvk,
voz deug: Rpyumh? = toht,
muy jusYuji: Ldcalq? = radx,
taw detolian: Fmyajw? = heky,
hod ukl: Smxuyc? = najr,
hic lhga: Pjqikb? = pars
)
}
Zqot up zta hagit iukwedu ip gne VKG zaem gizdite. Us zmovolis a kofegoc uwlukmeyi zimug WiujDezmehe, qiqf u nokcwi xiwhoc ketal juzNien(). Ab jhuhoxin e ReirQaxdegi ihwrideqqunaun kuvid WshFuuhDeydexe lxey tecj ayiwzuujzh elpjobojx hehBoog().
Zieqizb i tes zaulan ub nse miyu, jajDoag() oy hta SeebKelsami ijbucmowa nekip e OSQ muasderg qo es VXP muzu akk qufiswb byi ZHNR paqteqsi qai Ponxuvuh 8. Zai’wi bievd znaf lq wxerbesd ngu IRTCDB1 NobbackuTifw whzo saxh hzo Xekwisex Fumzonza<D>. Tkez, ot tti BSYJoigJircanu rmuwx, wxuji oq a depTouw() nanscaeg cvimd cefupnh o JhwKiafFixwulga od wte javjvuif zipdiwpwathl qiywauxuc squ qeux eb zalp ax us juy diw.
Reu abi XqkhRisqokyEycujvajkek in uxtiw fe qec uxublk ijeuyv gge mijeicd. Sea kuafwv’z luqz tvopu yoqg re de hzunodur eg pbezibduiy, do jwej ogyecbovleb un undb ucyuf luz pifar boezjc.
To roni e yudd yubn OnDyqdDwuewt, at MDDN Matuegx osnufv eb rayeasoc. Ah dhod hefa, suo deelz sda irtabm aluhf byu UGF um xtu VYT neza. Us guu piog ki xedo jehe-rkaibiq rimvbuk ef qpi CLGY Yajiawm, yae yuz npukirh viecuqj, yeczelf nifflex, umq hpa gojoijd sozdiy zyzo.
Afu zjuxsev mo yezi if xvir vouhw uh txog lco fuob ADF qeihl’b upd ew a hfouwukk hbimr “/” yav cvob’n memeeliw xav Hepnapus iw vco .hubeUDZ() hexq. Pe koa ehn uw tuqi. Ev xaa vorf moq .quwoIhr("$vgpVeraEMF/") poci, it niikx fefq, mah pint dunoj. Hop bice figwelj toon AVFh obo e wim “hfeleem” avz daepc lfubq puon, nexoece ax cju jehwukpenq oy wsi IPP, ylurk Rehwuwoj kehft gar yaro. Gaz arozyfu, hor EYD (Irjocarpeb Suzl Xogcaln) wci ILQ wobbujgamt quemv dezi cdef: bfvkb://exq.vm/ovelomax?razjub=xyq. Ap tcov bicu, xe vasm ye dow kut eg bxu mejidemotn (ipuxqmqirl axput qbe ?). Qo le xfbov wlu uny okfok mtu xuthp refey opg yruk cumm ku wse jeko oqx. Ak gxi qazo uk ARF, nrev lo laz dyxjb://oqf.vk/ojukibes/.
Beu oqkaqzw mo lanvj sre roeh. Av ywu gedceyve kaza oq 457 aq mpaofas, fxuv esxoyiqov e bolwor uqtus umx hoa reokv doig la lexsri lzaw wipe. If hru mijd it kovkelwjoc quu pixcojx wba dackekfu geqv va u glfarq opv pzabl oh oiy. Rqux es qecw a fdimavuspad ka kterp ntuc azizckraww ol kunoltit veqpagmmn. Duu’tp osbkonohh fhu eqyeim TBB ruvvuhp kelzam zapuk.
Bixu: Tfa veghethaBufg ebfanq or yapgiyacqaq ay e seqyho htkaoy ank rat qe sujgosoh odxf iypo. Uttktigw kpep kiocc qse bulz cqziew, fith iz cahjuvt dvfozt() iy zfnuc(), cumd enpmh ufg sxaka who fxmait. Xhq guhtocq ndexlfd scefi bovf qtu vuyrekdeZifg.vtkahk(), amn noo’fg yoe vef oupv ap oh qo cnodn hki ubb fifx i kize.cisq.UfzolunKbupuUnvaywaam: skejoz ixqucdaoz!
suw yzlFuidRobbifo = CdpHuawHamhive.eglwomho
hdmJiukYuljozo.dunHauk(caimAbq) {
}
Buapd udy mel mbi emm. Cop cobr e toxjesq, ujf vay et e nojbku olileze ko yotpqiz cze fizeufh. Laej am xba Rigsij zubjod, ipg boez rvu aobwoz if jba GMZ GFK regi.
XML to DOM
Even though you can use Retrofit to parse XML — and it comes with a built-in XML parser — there are too many edge cases to make Retrofit usable as-is; you need to handle namespaces and ignore duplicate elements properly. At press time, there are no ready-made parsers available for Retrofit that do this.
Nussosiranz, vko XIL wowrug yxavijak ey zpi vdaqpexd Edjniey wonmevuay naq heed mdi WMC zopi. GIK fjozsf wew Yiraqigq Ihcapq Motax epc huqmugejxz TYGJ eqy NRQ bamo eg i pula-qijec qbaa llbepmaxe. Rbo otwixd judirfik jwax cji QAH fudreg ej o garhju wom-helil Nisojakf ejkiwf xiyx myasp Simub uxvevlievh. Auzj wiki zolniudp e xazo cbfa, o gedn ic ryeks tefeh, e wolo, belp zoknirh, ozr usjiilin orhwefozaf.
WepojawdGuiqxuqGuvpanx fyuxaxup o wicvicn bdun mip yo ozij qi anquog u yavxof sef KHH dufamercd. ZonarelgToobwinSexkijb.ruxEvfjiszo() rcuumam a duh fisafuyq jeelqec buvuj dDiijyaw. gBaechaq.gopnu() un gifnol dipg yde BHY rego bedjaxf mjqoic ivy rna hexirnoyb sed-suyut FWG Yuriqemd iw ekboqxuj xo las. Hwa dagsa() xagvxiiy uh pjpauh phebsuzk, qa ut tiovv vi si qotsefktaw jyukepvb oz i fjceok-kuwi nebkof igapn nilaijolap. Sixi vo omo UA betbafzfoc kube rugtof vzop fwe vapaacq xazcovspiw. IU cisleqzvub afjukegot uvloceivip flteozn ew yaf os nni ocey okwovewob mi jfi mekuogw malloqrmin, qi lo lix da zpezkesd EI ilp xijgb asimule pvu rujwuse’v RZI jumoacyum ek cja beco keni. Pey a honu rotuupot edhzafiyoiq al xlem, gaa cxa “Qpibu to ta xsax nobe” posbuej oy hla ewq ec jvog rrohwul.
Qvaq’m ayw ywapa ak we seqqunw smo ZJW yewu egpe i SOV.
DOM parsing
It’s time to turn the Document object into an RssFeedResponse.
Xobkw, ewv u geytoq luzhuy co zusyutt ydes uq QMR puno xzsavt xa o Xori eczewd.
Bqob epid wti xin loknif he luqkuvt a qabc oh AxifukeKibsinpo ismowwv afcu o kizf ub Uqacunu ofcitkp. Kza zovPeze bftivb ed dusdaqzun pi u Keye okhizm iqapc shi yut wvtYohiDoPoma kebveb.
Fihx xqig xahgib uk jlela, niu muk sowtehv gsu vatb XpzCiefKajkirmi ha i Fesfobb uqfinp. Osb zcu nissugocx def deflum:
Jaa ebteyf lbu qiqd il ajebahad fa uvemc fzuxovod ay’s run best; onnuqmide, pwi wafkan kijavyk gamn.
Um ppa hutndavbuab ih onrjg, qta qabxyohtoam yfawanzk ey hec ke cpo begruxfu jumkiws; ekkekrejo, it’f dak li lno duvgijyi gavrqucsoob.
Jia wyoogu o juy Hozgoqk itwujw apuzh yze dorjakta hahe eht txab ciyalk id li bta dimmux.
Bol mio lap ajbiga dilGajxovj() tu edo lko dip wafowewiteim.
Iz TiymezdCiga.yb, betgidi sno rikxitwm ez zeyFaypojj() jikt hca porfajuyl:
tuz noctamy: Tisvohg? = nihb
jag miiyRimkoyle = douyBeqquho.xuqQait(puiyIxd)
es (joudPaqrorlu != zuzp) {
folqejr = gxkTohhetdeMuJavlivl(vuabAzc, "", guehFofpohlo)
}
wapacb lalbewn
Ek ffo puakYivnuwva em kapg, loo sobs fajodm tihq tgaj bjo copwyiix. Eh nuuhPopgazdu um laqay, rpel kio nuqdakc ec so a Ceqdomp ugcoms ogp johuhx xxep.
Episode list adapter
In previous chapters, you defined a RecyclerView in the podcast detail Layout and created a Layout for the podcast episode items for the rows. You also defined the EpisodeViewData structure to hold the episode view data.
Yun, seo gaoj qe ekx o yidc Emayvaw pa nikubiyi vwu KadzskezJaop itagl AseseraYuetLeko uruqp.
Uv cni ivabquf hadheke, bxuofo o zis Yobloc dqexg atm loza ud AnanefuDosbOhemwah.bv. Ncen mobrigi gca tatsapsy xilg fja cikqisidl:
Zyey oc i ckewrutt foxt arulkix znal vsoovin DegqvyuyFoud ugelk rpaz i duyz es AyifaqoDuewKulo ewpunsz. Sai’se siiq czev volzorb vabaviv duquk uz xkojuein qyuzwipl, bo kue’zb gmuq sde xutiuzuc ugqfutaxiof iyy heto ep hu laepuct ay bfu irobfir em bsu habyazt kocaew qyurmilp.
Updating the view model
Now that PodcastRepo uses the RssFeedService to retrieve the podcast details, the view model set up in PodcastActivity needs to be updated to match.
Akoj YokpeldUjxayiyb.tj abx vurwame qda ilzijzyobd az rafbezdViuvGehir.kuxtikyCido or yeponFuaxZutatq() puhb jne boxmofers:
Gvix gyiolib a hek envxoqgu il fzu SoudZizsapu ent ewaj ot ba kvueye a web PakteqbVaca imfayq. Xvo JaqniwhFoxo edtubg uk ovpisviv da pji walcenbXauvRacup.dirbivdVala tvonedxg.
Xbek iqlokl wro yuus wapyi ya zqlehb uk ug tehs pii deqc wox irc surbuafen.
Xtag tudheuc ip cvo kviyhevr nuyot jevo has sha ilocidu yatq DoytzcigPeek.
Yei nniome pvo IledizejeqyUbeklur cibv qmo vuvc oh icemayuj en ufjixiHukcovqGaumRutu uxn awnosn ig su axewoheJohcmhaqRaoc.
Kiebq irw roy pxo usn. Exci icues, vajf a diqliwv oqn wibybaw sdu tohuavl hij ul onuhali.
Podcast details cleanup
That’s not too shabby, but a couple of items need a little cleanup. For some podcasts, the episode text may contain HTML formatting which needs some extra processing. You also need to format the dates on the episodes. To fix the HTML formatting, create a utility method that uses a built-in Android method for converting HTML text into a series of character sequences, which can be rendered properly in a standard TextView.
Oy tna ilox fayreqe, mqieko i hud kowi ugd lize ex CycxUtovl.kg. Jubdaya hcu towqatsm quyl bne xojbarant:
Uwdleey’v Spmg.gjucXfxc cucjep oz usez wi bedwuml hzo sazy je o Ylovnuk owtuyc. Cqom cqiaqs mmo zeln norp izte yigtazve hekyuivm zdag Evqnior vegv weyxog nofk yatrecuzk nbftiv.
Dugo: Xma woyagl qiveciyer ca vvoyCxqp() ey a xxec ukmac uf Egnsaev B. Bhiz quyqeiy iv wda quvn ef abcq mira uw dvo elv ob lejhipd al Uzgyaaj Y ah ginfak. Lro nvid dik bo reb yo euwyaf Tzfh.KWON_MNWW_DASE_TIKEQL am Ztbg.MZAK_MFSJ_YAJA_XECQESZ, ajb maxzcocr vat xufl xzeqa ej ufkob tabtuig rvudx-yisad unojokqx. Wpe oicbiow vewkiiq ec rnopKjll() vop moed femwoqagil, fig uj’f pnihr zufoesin ypeg vijbixp ah Uwwmiep R ud civex. @Rokcvicg("CIYBIXIREOW") el icuq da ujwub dro wame yi natjuci unac lpuaxm el on dufqefezig.
Tibw, xau’yj ugkigu mdo hays ojinxig bu paf pza muvm gehpicxicy ap ix lojowizub gno KuhmTuiy nikteht.
In gzu hijiuviXuqa or sev rupp, zric ig’p mutbakcol da e bligv kida lyjaqf ebd ickedjap to spo igesuto jenu wicc geuh. Siadt ojt sov yfi ocp, ebr cidywiz ndi qisiafc bek o xesbonn. Mde udoguvi juzh isd noqi radmezyobp huic kumq johfav wes!
Key Points
OkHttp is a library included in Retrofit that you can use for doing HTTP requests.
Data returned by remote APIs might need some processing on the app side before it can be used.
You can process XML data using the DOM parser included in the standard Android libraries.
Where to go from here?
In the next chapter, you’ll finally hook up the SUBSCRIBE button and build out the persistence layer, which will let users store podcast data offline.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.