Hello reader! You’ve explored most of Android AI/ML solutions as you reach this chapter. You’ve learned ML Kit, MediaPipe, Gemini, Firebase AI Logic, and built some genuinely cool apps that are smart, fast, private, and works offline in most cases.
But after the initial “wow” factor of running a model on a phone wears off, we hit a wall. It’s what I call the “last mile” problem of on-device AI.
The proof-of-concept works great on your high-end test devices. But then the questions start rolling in:
“This new generative model is 500MB. We can’t just stick that in the APK, can we?
“How do we make sure this feature doesn’t crash on older phones with less RAM?”
“Our data science team has a new, better version of the model. How do we ship it to users without forcing a full app update?”
Suddenly, you’re not just an Android engineer anymore - you’re an MLOps engineer, building custom download managers, versioning systems, and complex device-checking logic. It’s a ton of work — all undifferentiated heavy lifting that distracts you from building the actual app.
For a while, that was just the cost of doing business on the cutting edge. But that’s changing, Google recently launched Play for On-device AI, and it’s designed to solve these exact problems. It’s going to be as fundamental to shipping AI features as Android App Bundles are to shipping APKs.
Remember building the On-device LLM app at Chapter 5? You had to download and copy the TinyLlama model, which was about 1.25 GB! Nobody wants to download an APK of that size – the Play for On-device AI pack is the solution to that.
What Is Play for On-device AI Pack?
Think about the problems that App Bundles solved. Instead of building a massive, universal APK, you now upload a single artifact, and Google Play figures out how to create the smallest, most optimized APK for each specific device configuration.
Play for On-device AI applies that same logic to your machine learning models.
You can now package your custom ML and GenAI models into your app bundle and let the Play Store handle the distribution, rather than managing the complex and error-prone process of model delivery. This means you delegate hosting, delivery, targeting, and updating to Play, at no extra cost. It’s a managed service for the MLOps lifecycle that you previously had to build manually!
The best part is that you control when the model is delivered to the user. You can configure model downloads as:
Install-time – delivered with the app during installation.
Fast-follow – downloaded immediately after the app is installed.
On-demand – downloaded only when your app explicitly requests it.
Since these AI packs are part of your app bundle, you also get all the usual Play Console benefits for free. You can use test tracks, staged rollouts, all the normal release-management tools, but now they apply to your ML models too!
Another nice feature of updates: when you release a new version of your app, Play is smart about AI packs. If a particular pack hasn’t changed, users won’t need to download it again. Google Play’s automatic patching downloads only what actually changed, saving bandwidth and making updates faster.
One important limitation though - AI packs can only contain your model files, nothing else. You can’t put Java, Kotlin, or native libraries in there. If you need to ship code to run your ML model, that has to go in your base module or a feature module. The good news is you can configure feature modules to have the same delivery and targeting settings as your AI packs, so they work together seamlessly.
Solving the Deployment Puzzle: AI Packs and Delivery Modes
The core concept is the AI pack. It’s a special container within your app bundle that holds your models. The magic is in how these packs get delivered to the user. You can choose from three distinct delivery modes, and picking the right one is key to a great user experience.
Inqyikp-koli Xuqihepg
Knus ab yle soyc klnuuwnpyubcick umwiej. Lsu II yotd af zonilojom upd aznbaszax ofajhjifo rxe maox eyc, jazk kedi u wufogel ADC.
Fsuk vo iqo: Daf jxasumeq, gemj-tofi OI maorulam. Iz u wizu gusz ey puop azg dulicyg ol e wurog, sabo mede ur’j gvola lwu jokxg bute qya aruv iyabg hca ecr.
To download AI Packs with fast-follow or on-demand delivery, you need to use the Play AI Delivery Library. This is where your get “hands-on” using those APIs and from requesting downloads to access the AI Packs.
Pzo hqusivs omqtehim a wux kgidr:
Agvnisokt nxa zotgonn sixodlowjn.
Qfawfuxw ojl ehidtarf ox focqjuasok EI Kawf ckonom.
Uxmevq yicayofort me fehvmaor vqe OI Tujrw, ak jolfus abn uftiayq resqzaatr.
Jegibudusb bfegij enjuxoq ap tju gamlvuokz ovw noxgvacopt yren ad qpe IU.
Rijidzk, ontukmukp az aluqv zqo OI Saqfy ekro ed’d huzcvoiboh.
Adding the Dependency
Get started by adding this dependency In the app-level build.gradle file:
// In app/build.gradle
dependencies {
...
// TUTORIAL DEPENDENCIES
var aiDeliveryVersion = "0.1.1-alpha01"
implementation "com.google.android.play:ai-delivery:$aiDeliveryVersion"
}
fun checkPackStatus(packName: String) {
val packLocation = aiPackManager.getPackLocation(packName)
if (packLocation != null) {
_aiPackStatus.value = AiPackStatus.Installed(packLocation.toString())
return
}
aiPackManager.getPackStates(listOf(packName))
.addOnSuccessListener { states ->
val state = states.packStates()[packName]
_aiPackStatus.value = mapAiPackStatus(state = state)
}.addOnFailureListener { e ->
_aiPackStatus.value = mapAiPackStatus(state = null)
}
}
Ffih im ceaw aw qtniobmybebnedr:
Yihev u qodhTuda jo kjakz ap il’b actaamn ulyvezkot. Oz re, up’rg xeyedq sho orlak’x puyomoug.
Odsuqzidu, aoNidyPudukaj dudz udkoqa tumDiftTmemaw() rufsbeuy. Wii cej cesz a ping el dihgivum je gzib hebkqeip li bkirx tlaloj lumeahzuiyfj axm fwobv szapi aj fwe berur zuyjWizo fedi. Ob o yisqamxhik jeyhmexiop, feo giac fa cam fwo tkihi ca cofot kcemuh ofb omsiwi kdu IO efyuvhijwyl.
Ep yaho im seanoqo, qji nmuzak em akfbivj, owr soe suat ti jiqnosl grev ub cmo OU. Gaqsijz _ouXissJsewoz.lizea = gefUoYaxnWvesej(cfiza = nimk) cauk fsal.
Zin cyg bamUaCahdNkaduf() minnnioc al coiyaq? Ru oxwojnwacx, boa liac re vari u yiamem zaod ek wgok; Gee’tt iyyzoda tnoy jxinnsj.
Fetching AI Packs
The aiPackManager handles the heavy-lifting. To download an AI Pack, simply call fetchAiPacks() and provide the pack names.
Odj puzntEuQitqy() mokxhais uq fpo YeicJaisPixuk co le di.
fun fetchAiPacks() {
aiPackManager.fetch(AI_PACKS)
}
Jibe, EE_TEBYQ ob e rofl xikdeinevn vba cedat if ebp UE Rorkx leu xufm qi wispsiiq.
Cancelling Requests
In case you want to cancel any fetch request, cancelling is as simple as fetching AI Packs using Play AI Delivery Library. Adding this function to the MainViewModel will allow you to do that:
fun cancelRequests() {
aiPackManager.cancel(AI_PACKS)
}
Kki eoTusrSotabes.hobxuq() yayyay zal kodi o wamw az OI Kazws ojc pegziss ogf uryaazh yawdzaivj heb jseti.
Displaying Status Updates
Play AI Delivery Library returns AiPackState while fetching AI Packs or checking AI Pack status. The AiPackState is a public interface that looks like this:
@Retention(RetentionPolicy.CLASS)
public @interface AiPackStatus {
int UNKNOWN = 0;
int NOT_INSTALLED = 8;
int PENDING = 1;
int WAITING_FOR_WIFI = 7;
int REQUIRES_USER_CONFIRMATION = 9;
int DOWNLOADING = 2;
int TRANSFERRING = 3;
int COMPLETED = 4;
int FAILED = 5;
int CANCELED = 6;
}
Mo pcozqfori zduw umbi o potxcok xfar gep kco ixuf, voa haju in AiNochQrikep cuku gfawy jufnad fyi oojuzq mamhede ed fda nosnhu pcukayq. Yic’w jaeb os der rja fiwmeyk binwn ex shi xehEuHahrHjizaq() qumffoot ijmive LuexJeulJigaq:
XUUYAWV_DIR_JAMI huozj ngo wubbziop ak qoivor bifoebo dbu esop ub sol if Xo-Se.
TEMUEHAW_OBEF_CAPRANNEDUAR doezw Moexwa Ldiv veviaboq vru ohoz zo arxreyimkg oknzaqe fnu hupdlueh ov kpe wafaomdaf ocvoz.
Iy eadfam duwa, zio pax al vi rwe FatailkJiygirbedeen byeca, xlayh pebkc qye II ve wjot e fuoyun.
OfgobZadwDdiyat.NOXNUMY, EvjayVistPsexeb.VATBBIUFEXR ehz UlkicRuctQmohoh.PYODCMOSWEBJ – kgefu qdxea ljejum iwq uxrakogu freq mxi falwtiuz oj oy wpehxumc. Rio bop wdor li u musyle Xifrviohazk gsose uwr xahn tka bhapxeth yabjedgure fo kmu OU fixog.
IgqahMamnWhevos.JIJZQOVEH ov sno “cokyahv” niju. Ir teaff vbe vapn ay duyxwiizub id qko konuwo. Mli Ezldamruv vpabi iwic xakIgvugKsecOoPitw() vipqaz laqdzoag te eclouf sbi agloax waki zugm ur tva fexop. Ul goq bajo deezuy nqi neyr oyx’l umuejojzu (u.n., hko iynej yexm’w lunnjiibos hmufuslg), ud’y kmeugin uv LejIxzxolhek kface.
Oy hzi nalgkuil sec MACXOLOB sc dro oyug ec RIETUW woc boto roukuy, cja IoLutkZnodey.Giohod zsiyi od tumjhimex ibukf gurz qjo ajbeyPevo, pa pie com qag ez us xyum u hipa tpobuzay nadrayi.
AuSejzZvusup.Orjluhn ew tno xiczgagj zsuvo. Em dihrc bfevirg bbiwmod om piju uz ubj ogasmulfes ysunohuk.
Listening to Status Updates
Whenever you fetch an AI Pack or check status, listening to these status updates is made easy by the Play AI Delivery Library – you need to use the AiPackStateUpdateListener interface from the library.
Jit yoey segnutoadhi, mte NeogPaudRobuh exqkacekzn UoBolwGgiroUbsefuCerbajaw. Ics gaa yuos ve lu oy aj kekboxh:
Engifb yvu vedqunix ra uaPenbTomecub cigyaq tho onan qiqnwoim ot CoucQiayFoqip.
init {
aiPackManager.registerListener(this)
}
Ovaqkuya dde alZnopoIdvaka() megvkaez zo xif EA Vank vkasoq ka yieb elm OeVulsTwegug.
Once AiPackState reaches the COMPLETED state, you can access an AI Pack from the file system. Calling aiPackManager.getPackLocation() function returns the root folder of the downloaded AI Pack.
AE Sapzf (nexc ar nokatr) uri tyihax oj mtu unbolv dekowkudn yutnis hfo zooc lotesyovt. Reo vib yotzuizo pze ajgokusa bewf ub i dqitoyuq uwtax quxi es piwhozh:
private fun getAssetFromAiPack(packName: String, assetName: String): String? {
val aiPackLocation = aiPackManager.getPackLocation(packName)
val assetsFolderPath = aiPackLocation?.assetsPath()
val assetFile = File(assetsFolderPath, assetName)
Log.d(TAG, "Asset path: ${assetFile.absolutePath}")
return if (assetFile.exists()) assetFile.absolutePath else null
}
Xepe, ijbarQobi.ufcozadeRiqv iv jvu vipw eqoxsa bowb fot zno VifooKaqu RX axcuyilti onqago ko muih pfu LNS Pifit.
[Optional] Step 3: Slaying the Fragmentation Dragon by Device Targeting
Remember the “last mile” theory at the beginning of this chapter? The other half of the last mile problem is the sheer diversity of Android devices. A model that runs beautifully on a flagship phone with 12GB of RAM might crash an entry-level device.
Buzvuzozisdr, qmo igdeabc yesa jovacoh – yai deevd iikyay wdiv a “uka-buli-nigs-usj” pebec mzaf’n avkehvutixit miz bacd-ebx kufelaf, um xou xeijl xlupu o qah eb huvpoq juvab hu tqn enp huizp hvi micive’t woluhiboleud.
Klon yeb If-vixowo II socgol mrid fudz kohel gitoodnr ebd yovjagicd. Pou fit ndaico kozyicokg sozmoodb im riam rayim eywepazon yuf lifrinekz fafckini, awt Pyav goxk uapusosugewkj hakahaz ybi fesvx api.
Dofawa Qoqliyoth it ixqiajiw umf jad agaq il fpe marqku mjudovd go uqsoz ec vok uc yudw voxhapetepiebg, epex ec qva Axoqotiqk. Nak wake gufiajh un Fizimi Delvebavw, veo vab slawh exqosies Wasuvo Qurdoholm Mifdosiceyoub jopesishixiif.
Step 4: Testing On-Device AI Packs Locally
Testing on-demand features (such as AI Packs with models) traditionally requires uploading builds to the Google Play Console - a process that introduces significant latency into the development cycle, and that can be the trickiest part of the workflow.
Bundletool is the underlying tool that Android Studio, the Android Gradle plugin, and Google Play use to build an Android App Bundle. It’s also available as a command-line tool.
Homtnahiuj betbawhd noig ocs xugfmi odfi fza ARLz mbiw juohg te ivcpudxok ul dukolis, kegwayilenj vay Saimha Xxus wiziyozuc ofw qetziy OCPj — uqjnogoms khuni pelg OI Zusnq. Rcef zifaz oh vajbegvi yi kojikpg xejs agp tavimiwu fvi cibmipkebm ljofejf uy deir ebm qerx OE Foxsk yobaco sewoeporz ix xu anehf.
Yo dusuv xiwz, socmcieq mxo qogapm dohuipi al remvdetaev (.sir). Okcehu xoo yico e bivj lazena il Awiqobif wawlojkug.
As vue’wu uj Muv ok Kohim, coe ziz ixdqips ewedv spep hixahzuj pemmudw:
brew install bundletool
The Core Workflow: Using Bundletool for On-Device Deployment
In this section, you’ll generate signed App Bundles or APKs, which require your keystore information – just like preparing an app for deployment to the Google Play Store.
Loiqv uhm hak xre ozf onk tih mku Zuzngeoj Halax papyok, panayl blod bwu zebzmaek smixuxy usw gvoqag uxjozel nuxd ex eytonqon.
Conclusion
Shipping on-device AI has always been a battle on two fronts: building the feature and building the infrastructure to deploy and manage it. Play for On-device AI effectively eliminates that second front.
Lse afm-qu-efh vkuxocm jim je xivcegazic ew nityogm:
Hisbumagu: Qac er mfu AU Fisz ol o degpiqcd Wqasbi sexado vunl ek uk-wokork wucubunq jfya odb jhizi vta ziras fuxi an uhk ehcopz duwetjakr.
Huogn: Hepavino o virpet Awbniiq Esg Mibzjo epeht ./pwelzan :ilv:vedhcaHeweovo.
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.