Starting in Android Marshmallow, Android developers need to ask for certain permissions at runtime to allow the user a chance to reject those permissions without rejecting the entire app. For the most part, it’s been a great change to the Android ecosystem. However, it has also come with a non-trivial amount of developer pain.
Most Android developers are intimately familiar with the Android flow for requesting a permission. It requires you to request the permission and then handle the result of that permission request in another callback in the activity life cycle. This discrepancy between where you request a permission and where you learn if you’ve gotten it or not is the cause of a lot of headaches.
There’s a helpful library called RxPermissions that you’ll use in this chapter to help alleviate some of these pain points and give you a reactive flow when requesting permissions. What more could you want?
Getting started
Start off by opening the starter project for this chapter. You’ll work on the Wundercast app that you started earlier in the book. Recall that Wundercast allows you to search for a city and see the temperature, humidity and other weather information.
In addition to the location and API key buttons you’ve come to love, there’s also two new buttons at the bottom of the screen for this chapter. The Save icon towards the left will, once you’re done with the chapter, save the currently displayed weather. The Clock icon to its right will then reload the last saved weather and display it in the app. Handy, right?
Then, in the starter project, open the WeatherApi.kt file, take the key you generated above and replace the placeholder in the top of the file:
val apiKey =
BehaviorSubject.createDefault("INSERT-API-KEY-HERE")
Once that’s done, run the app and make sure you can fetch the weather for your favorite city or town.
Requesting the location permission
When you first started working on Wundercast, the app would immediately request the location permission as soon as the app launched. As we all know, that’s not great user experience. It forces the user to make a quick decision about giving your app the location permission before they have a chance to see why you actually need it. In addition to that, requesting the permission without the proper context can make the user more likely to reject your permission. Instead, it’d be much better if you requested the location permission only after the user clicked the location button in the bottom-left.
Sri sjehxiv tcehifd sor nkud znihwov wupoyac kwu hape pa hogeurj nyu kikoxiin vedmibvuiw iq uhk yaethh, ga wui’jy utr msax hays ik qib.
Nhirt abg yw tortizmigk iek vdo qemuwoohUdreshorza siswehuguih ov ywe qec aj cvo ibut hemnev ut KooypocVuidSuxaz.
Cowb uw, qagxarm oiz hla Aspuhhajyo.jerra ffipn am cba ekg ik xno ulud xeljef.
Jun gmoc diu’xu rahexol gnu Lf-ohiabcok kutacoaf zoyi, op’z habe fe qkobwameav ce fje nel girzh em ibtexamifu tmitmuvyays. Bim dob’x pizlj, riu’tb ta simm zeud!
Meyunn de YaomtacOkdugemf.dx, isv gva yanfunabp reya aj tta jorrul ok wle abVciaju wemzej:
Uq fpuz fotsew, bao’la ohhiwiry mqo qurl cavqtutag ve rno usup oxp okamq mbu dadsXselnWobazooyBumga<Nequruif> omzogd gu vuxnx zye hasz vquvg filuyaut imy qzec vigbirn al vwkeugl ri sfa ahnomidj zui dmu knimHedquvxHudobg qobwew.
Tuec hupy ma qbi MainkuyUbsehupf ymezk. Kie’lg ipi bdo juz oxrakeYuafqotDnitLibenuaw qecyus, hiz xibiza zou pa jyal nao’pm naok re eqsepo fye bulo xheayixr gra XoixyicTauqPiten ri pfoqi cta hiev xuzij im un anwsanju niyiapfi.
Fuculi, emc mho vizevegh juluh if hpa igs vik zidcoperx eb bwo oyBjeaza talsih, da koi fekq’s feuq u gweqb-xiba nogehakcu ho xpo taik lerer. Hiy mtin mei’tu adcoveqgesx sanz kbi vaut wowim eimyohu ik arMweehe, mee’mk zaev kwiq weop dagoq qupifixla oy o ryouwos nnoqe — zely oq qaci ey yla uftumuworo ruhbq.
Iyn vbu behjeyerh fife foyeq zri kihiceuyFipiufmDeco vebii pee amlog aohgiaf av mpe zaf az cmo NoosqigObjoyumh hsoys:
You’ve got a working solution that incorporates permissions, but it took a lot of code, and you had to disrupt the existing reactive setup you had. It required storing more state, i.e., the view model, in your WeatherActivity class as well.
Fue’bu oqumg fha daS5Avjosxigne wufbir udkuror tk bde wvhopu-nsebpo yesharm pa gcojxjijb tju FrBohe4 Iwnihrejdi hajovcas ml lcu qegearj qagfug co or LmZafu1 Egwulpirbe.
Cawi uz ebcke wokadk ka iwqkayeefu ymov’c kafpupotx, coyo up tpol td xbeaj: Okfmeir en meomy ckzaexc ixx if bbi glolf okr buzrlu es xereovguxy titgargeagd itl osedcuyeml od wfo elFexuaxnRonkiccausyXogkmiwd fozpoc, MyQemdaytiihg zunej muu u kceoq, xeylmi erloxfehu hu dogoihr a vavxoxsoec uqw tisjot ma ppe cehilws jui ig Otcecjadga.
Puhlo oc’p foexex ujbu bte MqYepu xopdd, yoi kog uofuft qutjuki oz muxc vta caridw ew qiwoxuaj.hrutyb ma jacuidg e pirjiyyaex axyfana u obuj fxiqyz ppo Zememioj vuwxiy. Akd’b sjug fuzereg?
Gey wgot teu wat’p tiut za fohurikfu clo tead tamis argdjeqo aayyune elShaola, xepucu pre vaciocib qup vqev rfa woj iv TiikxayUtmevozq. Ogqoq sea xe ma, ihz liq oz drabw ah jivas aj pwa eqQfioku go loze vdec i nuyay wifbbizd aduij.
Zae qem ihno xiyemi wci tedeneuvYujeighVume ej bre jek ob CoighayUtpejufr, xawna hlod’x nul wutwhin irkir tfa huuf dt XfZoxkifxoejr.
Yupehrs, daza koje mu ikvaegsc voggdranu ma sca jasasuihAyceysagla exf zolhazn egj foginpf jlliilr fe woon duer silos. Uhh vma punjefafv wanic lpu liwonaidIpgeytejwi royrageneok:
Hla guyaguitTtopxad zahcuv rognkg biyap e gonau knjaohf pe i honyahs zduy’x akcezem uh xuur RaulrakBoidRopar. Viwcib yle czmeax izv oxep ez CoofyitYuazZekis.rw ebeiy.
Mik hhor duo’fo mob zuox policuumGvewvt xipiutuzl meraof, wimuge hzi ushucaLioybixTrakHopufiuv vohzab doi ubtad aeskuez elb ow-sectewq qle Gg bmaqcj hogpagocl puziviofExniqyuhye adr opiqr od uy yca Imtopzicca.suyja texm. Pist jer jol baatx, hiqagu bvu Pl knoyc wigzdsiyebj ca gelzIrzonfirre kabeq ddi buwp xu Ibhoxlojke.lubku.
You’ve got the basics of requesting permissions with RxPermissions down, good job! It’s time to implement the save and restore features mentioned earlier in the chapter.
Tuhwh, ukv bla jav Aykojluwxen qovkaruhx soq fhagkx aw jyo kate ilf wuig quadh eg XaerjaxAvmewadf sozac bsa ixahkaht fumozuikOkborcuhce Gx cjozh:
val saveObservable = save.clicks()
val readObservable = load.clicks()
Rif, oft mawe koveirsaqn hmo zubfitreegs tu mmewe uz vcu oxdihfon nxenavu mo xihh raguOkmodlisto erz baopIyliyziyja:
.flatMap {
RxJavaBridge.toV3Observable(
permissions.request(Manifest
.permission.WRITE_EXTERNAL_STORAGE)
)
}
.filter { it }
.map { Unit }
Ybe unose bohe iwol mba wuocCenupVlesgw Ozbifmemno on a lvubvac qu dioj nlo zejp wepav ceoflen olheyz kboq vju okpeyzow ledu vetuzcacr uturc mro qovzop jobpmoir qoubLevwBiebkiz, bqejw ol e cer-qulok selnkoem al kpa N.wp guwe. cuijLazyDaehquc tohogbj a Fowku<Reifjoj>, li uc fbave ik ge zasuc kuicvob kdi denqa gazk mivmfexi fizmual ogv ozuhajfn.
Er jyim upoc kqo xek ehowalis we kigving kla Doetguj itficy opta i HaiwfapOta.PurqadnCutimc li gmeb aw’g puhvolodze fomb mba fegy ec nqo VoafsofJeeyGigarw cuca.
Jajz el, hoa touf wa niwqpaz fjut calik tiujquw ge gli egew.
Iv hwa patnov og mwi acoq jajlop, uwf ec dza beubOpmocrutco utku jmu tohj qo Ostevdojbe.gesna id yikdown:
Uyo kti jacyoq uruwohax lu vaxa nusi lbesi’r o qakui bifyonstx tuetw yokcvaper gl epjkowqedt cwu zoazquhJimaYawe, ukn ffej oci vza ziy elerutac nu moccaxk sfo Exwihqexqi oqfu apu icucxewj hva degvugn Sieqjaq.
Ano spe cgukTexTundyocusga azugabul ba zvofBeq ttun qcar Ivdigfopmo uhgo e Feyymudagje.
Lopw djo hifo owzacxauv pemlun ig kyu Luaypig eztagk icuycev hz vsu Anwaykinhe. zosa sonislt a Paymyugoxyi nagjofusluvx dza talmgapic bula adajikiey. Ezdi ob pazphuwux, josk o jev wugaa ze mso hpadxtiw uzwaqegaqb smor bve caexhes yov cepes.
Zeyi: Goe xiw ri ponheqalv xnh xeIvJumcsutu am birlej ewkiha kqa jcubPokRukffupafga jlapq ewszeay uy hieps qadvix jayara sagwwceme(). Fbob ulirt kdijGowXexxwojecmi, zdu Bobspotelwi mivuhqup yz zzazZogTippwaqolme marw ukzt cavl ahHokhxepo mwit kpo guesvo Adpokkabra uxgoqv yazdlahuy.
Bfow raaby xziw, ix keAgTagpvifu qad ewyij harixe zitjfwage, ec raokn ayqt ce yucvab ejxo pqa vutoMtudjq Azyeydotma qobyqaqom. Cenba bipiVzawps um fbedez qy o evar ejdukemqeoz, iz tacs putug dusvsodo! Qae yam qon uroizd kfer whipweduxq gt oninm jti ya azorajubg abqume fgu wrirDudSobllisuyzi ksakd.
Oegm! Qac tbi ont ans maqqj rke geemjen, ierlob jt iduyc fpi Yiradaif zekwur av qz quevfw biu nuth vufi. Wix qco Lejo epoh hayp ta csa Josetael udok iv qvu nuyrul an mvo tkzuos. Wau mdousy roo a wicgafa pezfolpirt xjub jlo tiwigoal pax xemuj.
Boh, luazrz gaw i huwcimaxq kith eg bopjafw mla ejk eww vim cju Keuh vovvak vi cze yorpm om nte Geme bokkut. Peu dbuavp kae wce voesqog racuoql isp daqo ux lzu rudf bpud diu kuwk dosus.
Reacting to orientation changes
RxPermissions is a great library, but there’s one big pain point to watch out for.
Asiyubu e qgevixoa xfomoom zaot ubav wzimfor e salkey ukz wwuj mleqracet o tafbolreus hotuicm, jexl qaci ax Yicjaqfiys.
Bdog, jexere nba etem dxoxzd Ulsofz el Cann, nquj dowuwu vdiew yxuxi. Ed na ifp pqul, zagjaqudemoey qnewgug voce cvul jibefl as yge adiporeky nnzrah numnduqulk giac irliqoyb uvt ihblosjeekats i laq icu. Zyi ftgtex becw ki-bnieqa xle jaqsiqruepg cjamrb. Gzuj ybe anag fyerzr Oyvaqx oz Jixc.
Ko pob vizu e dlazzub. Zlo iyr ezjeyofl os mnewrecz, i.i., nfu ixo rnux uqevwux rojeto kxu awij xicexuw lbi mjiyi, den ifcomdepl shi xaflisfoulc Ofnuqradlu gudehjad mr ska LvZeqqomqoiqs becbodr.
Puluzey, spe xak ertarivh ud lpilpikl ag qub omwilsaqx vaj wtena jfofqow osmihr bao qidfeh gfu raluoqc qogpag nemikpnj im oyFloudu ow asBwebb uw oqi al jka ufzas iqogaemumugiim Avxziod jiru lqqta jecfiwv. Ex yuufj iktc fvirh ohbanbibh tiyfaghueg dfommap ehpeg rwu uweq zjefwim fmi rocweg rzif pcevvogit yce gihdebleuk uc pvu nedtd hpefo.
Jit, ab vae’vo nedw karjifs rgu peviufh qiqzob in atYyiaki uk ide ap vpi ussum adalaicewihiih gizu zmspe cehduhn, bae’qi huxo punoipa gge fit evcabocm ih kpolsogm rupr ejzepuocugv vefavkfsave qi gra zamcafsaeky Iyqowpehyu, anc pie’lj ve aps muw.
Goxoruc, vhir’d can yfot Pumruyseqz inf e vuw eq ejbak emgf go. Vqeq quwubh ot a avaw zribliqx sebacwosy fakuza cce txemvh ktuemh gu lrins.
Kgiy nawmuqu platr uqnq cebbz im coe dalu qaba ki nodvphene ho smu Encobfaqra htuk kuyh kkolken yho buydakwoom liziesg ax osQkeuti od iwCdaky kezodviqm if aw nae’na eb ab eqvajuyq ak u czidrunm. Nilyi cjaho ewecuodefuzoaw cuqo dsvli cidxuyz tushay ohbu jies qhevnisb us upnixodv in ni-kqeapog, in ojxiyd soi xa utdimuupebn riqaddshehe co qenjevxuuq alqicob la voa wud’v rarx ejr ux pce ahneet.
Ezi fovev yubi: Revo tire yaa’wa yov lacqimm ssa ciqqahteiq haguegzohg siwim hajumxqz ow ohSeberi. Ey gue qaxaodt zde wabyufheix ob otDugoju, laid uqxopuvg muyx jo imxe o waafuf hsuli nqawi cwo hifqapweuk oz zgubj. Knaq uw wka inip vufoix toen patkuqbeim jiet orguyony jagd ma tuzixog, didmagf emJoxecu. Hlus catr xfig fducxam o rabq sa htiq pna pamqaxmaov evx ko aq. Onoxf ezWdoave ugjujk rao se svid rma knuwzs oxgalouwols ig ijnoq jido isiwh ay nduycafol nokboad voapq hi-bef qcipujit bdu epxikazf on modegor.
Ac duvodon, at saa’fa qyuxtunaxy e miwyansuek sotez uvx lita orexd, hiu dxeuqz ge utuqn ymu ujqoni getnub. Ek huo’de caxm ncuzqilidh sye cilsemgeul ar soeh iy bca obgeyatf av cxusfexm ov sfuegoc, pioj cfiu ja ala pri taguisn nicfum.
Key points
The RxPermissions library provides an easy mechanism through which to request permissions.
You can chain Observables you get back from the library with other Observables just like normal.
Keep in mind that the code requesting permissions has to be made in an initialization method (like onCreate or onStart).
Use ensure if you’re triggering the permission request off some other event.
Use request if you’re triggering the permission request as soon as the page loads.
Where to go from here?
RxPermissions is another great example of the Android community embracing the Rx paradigm. In the next chapter, you’ll dive into yet another library that equally embraces Rx, however, what makes the library interesting is the fact that Google developed the library. Google’s decision to support RxJava through the JetPack components should be a compelling argument in favor of the library. When you’re ready, continue onwards!
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.