androidengineers.Book a session

Verified model downloads

Verified model downloads

articleSelf-paced

The download is part of the product

Open Model setup and tap Download Gemma. Keep the app open. The transfer writes a private .download file, reports progress and performs full-file SHA-256 verification before renaming it to the installed filename. Cancel retains the partial transfer so the next explicit tap can resume. There is no scheduled background service: process death stops work; reopening and tapping Download restarts ownership of that work.

Read data/ModelDownloader.kt. Resume starts from the partial file's length and requests the remaining bytes. A 206 response must match the expected Content-Range. If the server ignores Range and returns 200, the writer truncates and starts over rather than appending a duplicate file. A 416 response deletes the obsolete partial and requires a fresh retry. Short responses retain partial bytes; an incorrect final checksum discards the corrupt partial.

val offset = partial.length()
val request = Request.Builder().url(url)
    .header("Accept-Encoding", "identity")
if (offset > 0) request.header("Range", "bytes=$offset-")

This excerpt lives inside the downloader; partial, url and size are parameters or locals there. Identity encoding keeps byte offsets aligned with the pinned artifact. The final digest is checked over the entire assembled file, not just the newly fetched suffix. That prevents a successful resumed request from blessing a damaged prefix.

Cancellation and ownership

The coroutine installs a child that cancels the OkHttp Call when its job ends. This matters because an input-stream read can block; merely checking coroutine activity before a read cannot interrupt that read. File handles are closed with use. A verified rename in the same directory publishes the usable model without exposing an incomplete filename to inference.

Practice: break the network safely

Run ModelDownloaderTest rather than downloading gigabytes to reproduce every failure. Its local MockWebServer fixtures cover corrupt bytes, Range resume, ignored Range, incomplete bodies, malformed Content-Range and blocked-read cancellation. Add a 503 case and assert that no installed target exists and an existing valid partial remains available for retry. Expected behavior: a server outage cannot make modelReady true.

Also inspect ModelStore's removal of only the known obsolete app-owned model. Never delete a learner's original imported document or story photos. For production, design a user-visible discard-partial control and a background transfer policy separately; they are not implemented here.

Roadmap · Hands-on codelab · Pinned source

YOUR LEARNING JOURNEY

0 of 13 available lessons completed

Progress saved in this browser. No account needed.
Verified model downloads | Gemma on Android with PocketStories — Preview | Android Engineers