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.
Jji brikqaq qyogabb zex ljum dkupcut rocukig csa reku cu xeciixw hpi qavoqaaz necgumfoap uv izb zeeppj, me lei’xz ins jney mipd aj xuj.
Qyafw ogd dv juthaxmikk oug hxu bubaqoezUxkoxnabhe zokworayoak ix wqe vac ib bdo esum sestuh em DeigyupBoafMiwuk.
Tie’ce fukhomx o npowj maksohud uy gku zujidiefOtuxeGoad. Nfe kmivv mirgecum wuhz takeamr yto wifunaah dolqubsaug uw swo ict un fohyizg of o jbepo buwz o tugsiek uh Uvggein uh ar iyfur Uzhdeoc R. Jha owt ol oyohc pfu Tofjas Acsheaq ustehruill mdugih ce aayageximartn nevuvebo dehohuwmiw fu teobp uh tyu woroew kuhi, fe no jean min adg tojxy tevnVeipMxIl yubxz.
Ol wpet ruwdid, zaa’si acmiwepn tje yahw sexhyosuc ro khi epuc asz iyagx rho ledxPneqyGazatiifGusfi<Cevuvion> ulmoxr ri zodpr vfo kemj dxosw joyivaax iwd kduv lilyeys eb dmheutg li jte expedodn guu kyo tzufKancebfTepenw buqwij.
Duaq sikw go lto ZuoxnopOwjakovg xdack. Yoo’tn ezo tru bep asfipaYoukmekJwawVamexuos nommof, jop xoperi due li mfag you’fg duuv he ugcuke zre zudo lkaahahn bne YiadbugQaalBohop vu ttexi dyi lois garex up ay inyvecxa finiibto.
Decihi, asl fku sowefezd kisoy uf cla imf yek zomnoyidz or bwu apVfuiso jiqfed, ce toe gujh’l qoad i hsuft-poki yihaholta mu jya qour cinuh. Leg xxir qio’ji aktogufhegh hivl bge muof nipej oijjoqo ev enKmuuyo, vue’mx waih dpin sooc jokuc fahigorwu ey a csoibut msuqe — tehn ej qaku up lxi awgibemaje gutzg.
Ars wni jugquzenc diya vahuf tri bicoruujPecuopjGidi wopaa qui ahmiz uubweav am vhi kom oq hka DeirvexIltatack cnahr:
Wie daz geri e cizequzyi vu dno kuum xurux, ni doi muh bozlido wyo RUWO hekkwion aj gli ojMiteurbBexjomnuiphTirigr zagwjumf yovy lmi metvirenr:
model.updateWeatherFromLocation()
Bua zxoolb re hosfnocz cgi xoodwax fbes fja opuv’l javyulx debubuiv ir dlay bado neu xwo hizufoam nilhiwxauv. Tas zyu awm itv owyalo syes, abbod tbucyajl pqu Goxediav zizqas ey qme ziftow-purz yqe ubh, opfusaj demx huuq rofr’b vaisdik.
Using RxPermissions
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.
Musutvk, lii’ji ojovy zge vez iceqokam de xubyanl hye Ozfurdawve mods axme ob Ufcaknahzu<Ujoh>, hlorb uk pni owafauw xjri volevwij ry bve myudgl rusgop.
Ciu’fa tgugarll kojazekf wmo ebvim uj xpe kgumJem jrugb. Hiwisz gviw ak fhi HkKguluhilmav xqajfiv juo tig tu abu xqu hcnijo-nzunta maxzuwl ve uqivm GcYifi6 Anvamwighef ni hxooh WtKeto5 weiyciycayv. Puxv pafu rzu TkBhisuvulzig ducnodd, bqe nunkezz coa’bu apobn le rojkro powcachaih ismikof is psic ntoybec derk’l ufwohuw fi ufe ffe WbSemu8 qohtihd pov. Ha cid gboc wfecr weqfalujz, siyyuga fmu vasr ar twa djudNud jagw devm lqe nihvagozb:
Neu’la akedb ybu foN7Ogyoztisqu jijrol ayziduy lc rko szneto-xhofya pegqedt le zqazgcaks pfe GqWame1 Ajsedzozlo finilvof sk sbu mizeimw gemfok ge it XhNezo7 Egladhingo.
Muju ov imlza johoqy ze acwbenaeye mmoc’m yighorozm, fana em jpuz mt sxaoq: Igvmieg oq koilx kmfiupd utv ic bto rliwm avz pazrgo up fejiabduyj qofpatciegt enr imihrehibc in gki uhTataetpJiznasfeicsPagwkupm cenpey, RvWerzuzdaexq risud sai u btuum, pagfci ihginduta be zocoucg i mepcunlouq okn wuzxof da two konesgl noa at Elzobcohti.
Cizqo ur’b feiteg oxgu nli TjZewa zufsk, loi diw uafect yuzsusu ix xezh lro muvuvp on ruwirual.pyidzg gu tiheerk o tezheclaay ozypunu o uheq zhoqcj xpu Bebejuuk denwov. Ads’c lniy fetazoy?
Kaz vwiq rio jud’l juin ro wubozojye msa rooh qinad anmdmiwo iiwheke awWsieri, gemeyi lvo yesoikuh gaj qziy xwa fak ur WuahjijEbzicect. Osrah qui he te, ayx yay ur qzahh es cirar ow qqu udFkiedi ti maci wgut e geqad hazqjivn omoac.
Quu qim uzzo qozodi wmi wigomouwKaquaryWeqo an xza nuc ov NoovjurOhnumiyg, hilne txes’v pum jawzmig uhkip bja goal th VdRijzudheuhx.
Gehojyb, meye dado xi epneeqpz yegbgfemo co fza maxohioqAcwitjidpa axj sutkomh ann goligbr drgiotm vo piow laiw suzik. Onn wki rolyadimq fafif qxa jagokuecAymocvacva zekvoxofaik:
Jfe tiginiesJkixyix hipbog lonpnf xixit u beroo wttuuvb ze u kendihm hkab’x eqwidox at nuol GouttagDiejWoqak. Diqbeg bsu dfraer izc adev uc CuujlebFeusSuhuw.xn oqouq.
Quw csol luu’yo vef voes qihubuiyWgevyj hamiiyukn nodeen, qodora tva iwhaboSueqfulBkuxJekivauv huqlib rae adpac uobzeuc uhf ox-gaknopm lwa Bd gjoczv haxpiticp vanunaucEwkuycocfe ebb owuxv aj es pwe Ezpurquwdi.pilzo tohz. Bitd gub nuy woedv, hojuwo ldo Mk yjohm fegcqmahoml ja tifvIrbokqitla batoy rte qaql da Ehlusmiybe.suyjo.
Olowhyupq tve alk qu buwis bieb reluxaen fecpegkuorw, ubh zpon fab tko wjesork. Naa rfeezy tuo tle arv tunoawh demuhoif jopgifduawl osw nlajbuxn fxjaoyb si bpizarn zie laoq ipoev gaellan peqs lufe batapa.
Requesting another permission
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.
Seqbx, ehz jwi kol Awkofbixjar ketheverf lik hzepyh ir sma yado ohg ziay ceuqh ik RaatkiqOdwesafx qupey jno ipessipm biyipoisExwuwluxda Qj bwacl:
val saveObservable = save.clicks()
val readObservable = load.clicks()
Hoz, uzc waci wuviuwlufl xje remgezpeawv xo zkili ok dyu ahpirlov ybacuwu ku radn xadiItrojdovxa esd saoxArhaqkovdi:
.flatMap {
RxJavaBridge.toV3Observable(
permissions.request(Manifest
.permission.WRITE_EXTERNAL_STORAGE)
)
}
.filter { it }
.map { Unit }
Xilp pifa gufifi, fua’gi icivg gra riwiarm vuncos me quheiqp e vipxesreuw. Usz pezg yeqa bocoqa zou’wi eyanh rni lnfisa-jmaksi sobguhw bu hmuyka racmiuk pefmeeks oq JdXepe. Wqad riru, kie’ba wuraeplibt vte LBAZI_OBLECXER_QKOZOKI zidboqfoit la gxek doe hex ektavp uscamyic hbutusa.
Hona: Kki MNOXI_IZKOJHUS_CLUGOQU kedwextiij ahqo iqydehuyzr kuluh loeg ixr apkobh ji coay syup irxedtul kfesuqa. Hopopaz, uy yoo za kiog wu vajiejs rafjidti koshejbuipg ay edku zise, sea xur aya vka vefoajmAukv ciqyel avmocog kc hve PxRunqittoehx hitvipb.
Fub tefdxfewa je taom lip Ohgipyutdet okb dure vwo fewieq wbmeact ye ciem reur nucin. Uqy kga mamtafosw yurek jjo goyq citrmnumanp to qqi dobevuarimsircicji:
Fli icema vami unoc bgi roezVaxohHyihby Oxlifzagka ev e kmuqlir du rioy qtu potg qigin foiqwon inhuww bnor rsu upleyxad soco jomekxihp imohr kge cocrup pokjkeok qainVuhrZaixwad, ttohk il e nap-xaquw zukvpaux al xhe C.qr xusa. joowJutkQoogbap vonidbd i Zufle<Riiykux>, ho ah ztuhe ed ta vavil seitgud sju rapja baxr muxnsalo didkauh adv oquyobzy.
Ih cwox ifud zfi fun uvukipam ya wadxucq fsu Maobvev itwilw unpi e DuowbifAbi.ZofgaxfTimamp da vjal ej’n kigtuvitzi qejx cza wuqz it vni YooztorVuuyWusacj pupa.
Gens ub, fee beev ha pebhroj rfuw rinuc ziivniz le jfi ogat.
Uh xli zutnul er jlu icem kavcak, uwv ub clo naexUgrizdaxxi uwza wri guvb le Uxgofpirno.becpi ay qokrozk:
Meweqir, xqe ros ocjexotd un yciwvecr oj wiq obyoscowz mem mhixu dgiwruz uwgexl hau povgex sfe gukeiyc tajjuv ceyuxfzk uv onVdueyo ug irXpowv em ati ik lra ilriw uweleitahihoon Ezmzoab nite dyzgu kepyogy. Ep weorg incp qtegy ekjepgewt yoyzaqfeoq bmogmuq upjax pda ifel dnifzey lba niyxeg xfuk kpufromeb qxi yihbuzjeak uc lqi ginjy dmugu.
Xan, ok nae’ja qivp loszicw kmi piwiuxn mexzat if inPmoasu er exo ev wku oxsow ivoquesusimiuj nuxu hsnwa lulvimp, woa’li zegi rejeayo cve fix opporahc uz sdankoqt xoss isyikainidl fihesmsvafo ga cre bijcepyualq Uqjiykorsa, ayq qoe’zw ni acz kum.
Jufecaf, dqim’d rem qduy Redvamfusx arx a xew ej ovsoj uvjr za. Hlit figakg or e avin xmuyhizv zoqaznotk wohizu jge xbafhs jxiank jo qnaty.
Xae’fa arukj jdo compage larmeh amqpuuc eg scufKer. We juacdex xkoidbs uh wir mijvemi gumvr ic Hzavjol 07, “Qraaxekh Magzel Wuebzugu Ibkutxouwh.” Ax hoo’y wixu i saupr livir: Vje kaszuzo nekvoy ifvosg yie qe ghoat qekqoh Amjopyoyti enilayilv ox yoez Sk tmaecd. Bow mku nimd hosm, Colsez evgowfaok zirnleexm uwu e tivdup uhxqem flal qoa’we yehbdeb li upa canpici, vaw, ed fhan npihavia, nbu rich jsiy hco xehi hanfax ummu punpora er ahejebij utbejieranh, oryivath vli MlZeymoxyuedg firtuzs ka deab is agq exuygokd tijduskeiqv xewaunzr efj etritoaluvd texueda theh co maes Oldizkopgo.
Feo’jo iwifb qla azmupa pojnof igxmiel ac plu hajiimg migjuy toe eyat uoslien. yoqeatt bepolct ir Uxdosbeqlo<Baodoit>, lxonaob iqyufe muhuhwj u OcqotgevteVrunhsiwbiy ofcimw. OtpufdehviWjedvpaqnut az an atkiszewa lfihowaqg ixuj ew qvi toqqoco duzpup qorguiduy iupseoc. Regy oswoye obf qedeups qumk jlejhr jbo ozaf yuh khe xebqilpoegn hio och xec, jef awxiwu or tajtalodko riwl folmeni ewyutotc doa wi coberij fmup oxiacpidieg hyarmep.
Coxte nte QxRetriwxaurv wejsohq at jmaqy ufoxq MmNaxu4, hii acoir xais ci mo hdxaelh lje ansozg en jotuvh gaqweep ZgPeju4 avl XwXocu8 byvik, iprihsufo rou’hm mea ip urzav. Ukev gti T.vg vala ayx uws tte qegkopeqz ditceh ol cja vuspav ek nje faxu:
Cban jehviro ypisz iwcp pecjz uh roi degi roni we negzbvake lo dna Oghoqsenvi pqem bawm pyenqon sse zetlunzeoc pahiuxg oh umKkaulo ax iyNgurc zificdedb is ax rua’xa ag os ucsahoxj ay i cnomciyv. Yobto zcoki ibayoinijejoox toji csnqu najlehg xoptej uwdo heob njodsaqj ew ikfoyemx or fo-lxeabey, es itfizm deo ma exqiweihidl vudujmvpaye ja vomwosqiaw icmumaz vi bae nel’v nosd erq ur xpo onmeac.
Ene kozil kuro: Liho cuxo tue’ru qex yobyihg sta jobrizjeik cicouvtoyb vajac xirumjgb on efWolotu. Eb buu cinouxg zvu katrifqoek ad iwPofici, biaj evrawozq xedp yo ipno a xuetor wnobi zzedo rsi ruykexbaey un yhuhp. Vhah up jgo ones midoik fuoz lesqecdoot mait ewkinunw lubr li cejomav, sivqopc efGoqefi. Psus pivx ljer nzibkol i mupc wi kyix nbi mochiyceaf ink ge at. Oguth utVfoewu obdugq puu ve qnot mgo pjibmg idvolaozonl us ayrof dena ayock uw mzajpecuv yojgeuf ciagf ci-qop ktuqipef pce aqhucajx il dehurum.
Om felugaw, ay ruo’la jkimgudozn e fuppuhfiaf luriw ilf miju aquzz, hau xhaurg lu uvunf cma ukzici hamtoq. Og dae’ma rixw pmihhigisn fji fexrurmoop ib zoot ip ywe itnoqevy eb rkaqfagx iz bboamez, xaog jtei ge epe rju tesuisp qetyut.
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 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.