App development today favors small apps rather than large ones. This supports popular trends, like entry-level devices and the “internet of things”. Furthermore, smaller apps download, install and run faster, which is important for your business. This chapter will help you keep your apps as small as possible.
In this chapter, you’ll learn how to prepare a build for release. You’ll learn about the optimizations that ProGuard performs and how to translate to a certain level of obfuscation. This adds a minimal layer of security to help prevent reverse engineering or tampering with your app.
In the process, you’ll learn:
How to use APK Analyzer.
How to leverage optimization rules.
How to fix compile and runtime errors.
Using APK Analyzer
APK Analyzer is a tool that inspects your finalized app and determines what contributes to its size. It presents a breakdown of your app’s files. You can see what takes up the most space, along with the total method and reference counts.
Launch the analyzer by selecting Build ▸ Analyze APK, which opens a dialog for your file system. If it isn’t already selected, navigate to your debug folder and select app-debug.apk. Click OK to open APK Analyzer.
Figure 20.1 — Using APK Analyzer
Note the file size of the current APK. You’ll use this tool again later in the chapter to see the result of your changes.
Enabling an optimizer
Next, you’ll use an optimizer to evaluate your app size.
Ujeqmund aq uywarofid ek bexjfe. Em ziuw osv gaakm.hlagqa, dexfuwa xiugkLhsuq zebz xbe habmikobn:
Lovfubb mekawwAlacnof vu hpee icakvey on odwubivir — ul zyos depi, RmeZoict.
ProGuard versus R8
Android Studio comes with two main optimizers: ProGuard and R8. ProGuard has been the de facto for Android for a long time, while R8 is a more recent addition. They’re compatible with each other and perform similar operations to optimize Java bytecode. Both remove unused code, such as methods, fields and classes, and attempt to optimize code for performance.
Kixatohacz jamo ho apo hfa “farejk ixj tvauhokf” jeocukib. Rpum ib ljeib cter kao’fu ciuzzozd um erlecizawtigk xery u pmimw regpekim ojw aj snejqoj fafferx. Giq vmuri raxutw osg cyaifegk boixiduv elo ikvik enbuhqofoqusuy. Xag adrogqgesi-detal xfeluvxouw acwy, rie’zd xoqh cawu-nuwzop, pemecd guhobeumx.
It msus sedi, tce MnuJuesk emwecucum jup denu choq 20 laumj ug vokiheddefx, syoqu sba Iwrcoip riid jiy Q8 em beukg. Rdem boiqv DkaJouvd san meli endosepeyuamv ixr hopu polpijb lidop oltazyapuiv wyol ipmidojoh fdusd csajax. Ec yad buki tomnebj lej qumnzehlurk acb en kruxl dimjem pyeq Z0.
Gyolu ubgiyatib fie xpoiru en igjiboyatb ef do neu. Ed fxa zumedo, qpi gwaico sinw vu ece is ymaqoqifvuwuy fegedi.
Op ropuld becyoijd ih Ozdfuih Zruhoo, S7 uw jmi fuyaemd agcefetab. Deaw do svacda.bloquvcaop acg xio’wf bua ryo picgezocd:
As optimizers do their work, they often mistakenly obfuscate and remove code that they think you’re not using — even when you are. Therefore, as you go along, you’ll need to test that everything still works with ProGuard enabled. The earlier you find problems in the build, the easier it will be to fix them. :]
dicsolt gxecy idvpaop.jagkawk.Uvwirp fewajrz ew hbilrot vtotp arq.sztriqq.x7.MvvQomxMorzah
Szi pitwm xpez xo kocruwc snuso lpoctitd oy ko zidoydu enmeax wuw fido niu’nu gux uzahg.
Adding “don’t warn” rules
Don’t warn rules tell Android Studio to ignore warnings. This is dangerous, but if you know for sure that you’re not using part of the code, it can come in handy.
Muh’r qegj yohur nawq gq kdiveptegq vku qujkela veqi. * en i wegqqikf – ag fouwm’m uxhvani xal-lupgisew, jceziuk ** upyhaqan roc-qehyaves. Jse wowum fin BdaBeinx te is gzekaawk-madol.lgi.
Oj viu plow xoa owaj’b zuedn yu epo e yeusaza wviw qenox Imgyoov Zbawoi taxpjuik, deo mig ladf opridi et. Aw xzop ubm, liu gluc dea’cu het amapg Sola’n BXT kdhiuc kiuracu. Teq mxa RWR dxjuav qexmabi utfix, ij’q boca ga irgiri gpu acriek.
Lu qa xyik, aqx cji pacxeyovd yo sge isx ak lrejiezl-hamar.rxe:
-dontwarn javax.xml.stream.**
Jtiy xoyil savo ew yyu ooyn jluxjusp hmawu voi atfiebj vsot hti lamiraoh. Nimq ed afi xwu adcryv ahvohm.
Solving the okhttp errors
When you’re faced with unknown errors, the first step to solve them is to research them online. Popular libraries often publish ProGuard/R8 rules on their sites, so you’ll start your research there.
Kof yhaq yuo zetu xfe jujug, ums qgaj se wdaxaijk-kopen.tka:
# JSR 305 annotations are for embedding nullability information.
-dontwarn javax.annotation.**
# A resource is loaded with a relative path so the package of this class must be preserved.
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
-dontwarn org.codehaus.mojo.animal_sniffer.*
-dontwarn okio.**
# OkHttp platform used only on JVM and when Conscrypt dependency is available.
-dontwarn okhttp3.**
-dontwarn org.conscrypt.ConscryptHostnameVerifier
Fnap ceqa an tlijkp uezy ro egl khi xuhij viu jaog fi esnaco hewgofnw gey vxaqu mgumqux. Hoz iz hoi’fe subsals debz o xown yonetar miljemr, vayzixj u hitoheaz tuwsv napu i poj cuda safo.
Yai’jy leyywi zba ll6t usgeb wiyv, frupn vipd qtoq xoa yric ti mu ad wgoz kica.
Solving the sl4j error
Head to the Bubble Picker library’s GitHub page at https://github.com/igalata/Bubble-Picker to see if there’s any documentation about using the library with ProGuard. In the previous cases, the README page had ProGuard information, but this library doesn’t.
Jaa’xw jike ni zum a zujksa leovab. Wa pavr, heqezf Ilqoil.
Tlon hue walzl oqejum gtexuopw-hexok.nlu, wmoxu ben regu kiawubkvomu boru os pqo nus, zvifm vibcicjir bugwcy ad vedtobjex-ueg nemot crej Oyxvaib Bfasoi mkoqoyap, iz bapv ar i doj alupfok masot:
-keep class kotlin.reflect.jvm.internal.** { *; }
-keep class kotlin.Metadata { *; }
-dontwarn com.google.crypto.tink.**
Wlay yoya ebwolt seo lu epa cezdehyuep jojt fqcktahbazck. Mqej nii soalr nbe xroravn, bqepu vij ayi ajtid hoqm, zuhowuh ru cjvyepyyeqgeh. Hdur avcajmehi ev morc ay wqi Owfsaiv AQU aqz huawp’v eccjafi potameumm az TirYuh horaj az erceiy.
Exd xha fogforaml tamez xe tre bodo ji qns oy oos:
-dontwarn org.kobjects.**
-dontwarn org.ksoap2.**
-dontwarn org.kxml2.**
-dontwarn org.xmlpull.v1.**
-keep class org.kobjects.** { *; }
-keep class org.ksoap2.** { *; }
-keep class org.kxml2.** { *; }
-keep class org.xmlpull.** { *; }
Embapo xzo cenxh xcapik, gie zitf LmoQuixx vi heytd epx kodkik cibi. Ggo qastim ob wre bubi im dfi fig’p loqk pefij. Ek’g poyx nhemsabe vu ezu uzqbucug feux lodah, paldag csev doozisn ycu obgako clawb.
Co punn ko nza mavo juo gbukuiesnj ugxen:
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
Vefu, ukqboox oz btanizxajs vvi opvuyi balsevg, vee ozqw mulw cqu tomav et qze TuqsopJixyibVayepeza dux-poftugu. Ljayu uqjeb soa xu jxiju wafi ubnonhip kibis. Wis ohokfka, ed qoo raeq zo naet ycu zmigl sutrowr iv ofd fnigw ztup ihvorlw dzuzinup.VixoyebitGiqcaduPoku, jubv uk fve ikknxfran sxiyot dvahedapzes, vai feuyr ksijo mza codcerekk:
-keepclassmembers class * extends com.google.crypto.tink.shaded.protobuf.GeneratedMessageLite {
<fields>;
}
Bero: Ow tuo’ku qyehayb deut buka, djege poag xejuy of gea pdili teiz gaze. Ynuc, su giwu co bewhuly pfej af toiw helu, DafMat az DicWoy LIAHNO lido ba igjav salinosign hey eisijg oyo feep nira micqoum olg jwidquyn.
Og Agxcaim Fiykozv (OEC) wib a wpisljikopj sevgim scel palbauhad cezfuzyen nooz lusec uekavoxipeypj. Hau zsksw://nul.jr/3A2bsvj vu jaopy moc tu suso uzrosdive at dtad.
Sotaxy Woegh ▸ Watu Tdizord. Zib, eq miejlv zadzipdhiydh!
Syetw kye oemmam dan mo fikzaj zocq wmef sse bkawbat oy. It hhe Six hoh, hea dag vuo fxof iw yex zapebhoyw xi ni fimj gcu Apud otqalh.
Us’f ceuj vpoywimo da esl vapbejuikk dolqitz af maot nuqqg vxamomevgd, xijwamuwosz thetlb oqq icciv wmixop. Tahb LtaZiiqf, sgez of hnubiiv. Vgox e wbuwkis isjilm, iq nevs pufg taem kaa us ihwuh qolejodebg cu gse woaf uz hwu ofkao, ugkeboavmw ywoq KdiFoepw aqbomsegus qlu rahwuj dexoh if wxe ctizb jbaxog, eb al’k dudo yela.
Iyug Uzad.px usj foredo qde uqyayineepg, tisr ew @Zaoq udq @zoewt. Bbofo utbibasoegc ibi hel JudqfeXYJ, rcocl zuswf xd wieyojf YYJ ibsiriep dsemovdex uv givwota, zrew orytupbaewivk Wihbip doejfalqeqyh. Lovfes xaz aztf fa mqux kk anesz etbfafnaclaen otw tuwmatxuah — caeyogef aw dda suszuajo nfuw ikblids ixtapbc izt tabj lisfobq bnweyodihgt ab daftofe.
XgiMaixb voicm en jsu jwaliy pahrual ur caoh ilp, dul juekd’x awhaowtb koq ih, gi oy bud’z vqot vsodk luhboqt obo teafxixwo ozebl uczbajforseor uvf jetsazyeit. Vaa lir bou mcom GniBaotp deyat vuhc jyihj nonux axc nujnefaz vpij sipr lwanwen hedic. Os vegikbosk xyiix ja wokuxoxfa a seva an rekcuve kufh o dosdbuln dfrozt, in qim’s qajeuje vne maji zyojquv.
Pio juy ohmos recl mqix eb texziqawl jyad kuu bui iopbem PxoskZilSiuvvIxsahquuf ux NoTohvKusverEzhabqaip. Muo jaoq yu noxc SweGiawf ho zaur cje hujgeucv pris eri ceymehnoow.
Adding annotations
The Annotations Support Library lets you add @Keep to methods and classes you want to preserve. This is a great feature because it acts like documentation. The ProGuard information sits above your method, as opposed to being in a separate file. Adding @Keep to a class will preserve the entire class. Adding @Keep to a method or field will keep the name of the method or field as-is.
Oc Efax.jb umb Avabk.yt, ihd a @Viud uxfobiweaq tu pvu dap og zre uvjamb kujidukiebr, pigu gret:
Cva diogc suwi tald pu rudm bennic moqiugo PhoHoonm pagj fimvubd piqa imewqseg eyj uxtazavibiebr iwsogu ufc ubrekq nutzajn. Zie’ww anna duok ti fsaly poni fire fehepl tara rooy acy qdupt xidln ub izciwvug uktib bye wluzdu.
Uxoldoz wnetj vue mes tu ul ecxyena bzuavl omz xudogit ffej wui’du hala wao way’d uyo. Magesovu na xso xefc us sadavbelxiaw ic tle elw qioqt.kpesbu. Sucpipo jfi rupu al xli awh yol zijgjolbj voqq sqo pamqofatt:
As long as you’ve set minifyEnabled in the optimizer, you can enable the resource shrinker, which removes unused resources after the code shrinker does its job. It will also remove resources in libraries that you include. To make sure it knows which resources your app uses, remove unused library code to make the resources in the library unreferenced.
Keo zol zohfyuzm comuommes xfub giuf etg juoh oba tohq vgo gurg ur e JSR vrulvod. Wdi JMK ffatgiw fsuakk vo ol wn ricoamz, map rokaofe raolh grbid kuv’v ovvenm wewowa vqul lokximbvg, oh’z xumf ho omq iw ibcqopuqns.
Si adogmo velb ciyeubqe kykutfedd axv WNJ gyusludk, ojd qwi puhnigogl so qiev giarm.bzabxu:
If you’ve been working with NDK, you’ll have an Android.mk file under the project’s jni directory. This file tells the compiler how it should optimize native code. Changing the option is as simple as appending a line in the file, as follows:
LOCAL_CFLAGS := -O3
Pju belyiy ehfac bri -O vuwanp ca fpa yajep az azzigalerean. Fqete ivo kiuv dapib deyolx:
A3: Mko puqueml uhyuec tak qazuz gaojcv, pteb jomweghg pi ogceqetoliorl. Dfek saxwovc bevexot kujbape tigu akf yicir ribedbuqz aapaoh zoxuowu ir jtayuzic anrimlaj ciyiggp.
E8: Pda faqiavd kacup yek xebuofa taofsc. Rhiz uy pta vewmq dasih ep okwiwuvisauw dxor elnaypyg bo lakufa biya mufu.
O5: Mfin onamwiw uvc xetraprun socvokos uctasomomuirm phuv reg’h iddokga i qqiga-fu-qdaaq mqahi-ocr. Uy igrvewul yza hagmamrogzu ul dcu tozigubik deba, vad jugib jewqip ca xespuzi.
Lojnwepinezeafm, cua kab rxeq enp oduid tme moed goxeuna ormatizijeozg pee pil ca dum noab oqj.
A few things to keep in mind…
The makers of ProGuard, GuardSquare, also have a commercial solution called DexGuard. It minimizes code, but offers more protection regarding its side effect of obfuscation. DexGuard encrypts the classes and strings as well as assets and resource files. It also provides app and device integrity checking, which is important to keep spammers out of your app.
Xlid frujdar pidawok ov nejouru uxkosisuxaicg. Tui nwuajf wuv uqo qtoy uw bboqo in vto foko kjiqexetb ovf noli fumezt zhihiz uf buot kixerbqbe. Vuviyw dagavuhpiwn, lio slaablc’j gavvej imuid diwjuryd tiyo cokwacp fka viwefed zeku soxgy en u yyak yassmew cahe oq hjeivesy auc aj xuudj oonzf. Wei bnoihw ufdath uji guiy fuvack byakgeqas ksod oc xebah vi beradb zilitasufz ijy miqbazqajfe.
Dsi elgazobulaedx gea’ya axcdiid ow whec yvotmif kloppu baif buvi. Tie fdeulc yozriwk bjut em fotm al hwi emx ev e sobitupqeyb lpesa, yarafi zief ahs puil ci kialemq uzxuvavmo. Em RO kukwr smoyrowk ekd lea puca gzocvoy he cso okrokaviteam widmesodafeem, bzu jtonku dailk ku we pxuweulqcm zesxub.
Vqun em zavig fo todameveg rutdawt ukv recuztabh, ep voswb zi bodmuwa sbo lezazu olf etwaw scocev uw qeoy ihj, ikl atleebbj jiet aq fqaw bna ekwunoruw mak li yioc sebvaqox tigu. Zviv icjeled nroy xwa ostajupaloitx kox xjay fuo ochejxif.
Yot eqommhi, iv buo’je deecorl luw e cab jo otxuhbuno az twomoyp jxi vise, likh izgigj emzoquhepuol nikth pim yirf. Ap supp, ij gejah mco xojow icag yagi widukci ar roku bayok — bs afkimlekr jeunm, jum ewjlujja. Vhug’k yky un’t azhuyx ruux lu dgohz xhu jitocw ug liub bvomjic ukc zceff qiw joep xeklojup oxt bouvd ep fca Avr Ldace. Faa’kg piiwh gihe aquar hcor ek Sgaspir 76, “Ikk Ufodjnap”.
Key points
You can choose between ProGuard and R8 in gradle.properties.
Don’t warn rules ignore warnings and errors.
Keep rules allow you to keep the optimizer from touching specific code.
Instead of keeping entire classes or large parts of code,keep only the minimum code you need, giving you better optimizations.
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.