๐Ÿค– Android AI and Generative AI

How to Choose the Right AI Model for an Android App

Picking an AI model by leaderboard rank is how mobile teams end up with slow, expensive features that work on half their users' phones. Use this framework to choose by task, privacy, latency, cost, quality and device reach, then verify with your own evaluation set.

โœ๏ธ Yunok Tech ๐Ÿ“… Updated โฑ 7 min read ๐ŸŽฏ Intermediate
On this page
  1. The principle: choose for the task, not the leaderboard
  2. Six questions that decide the model
  3. Decision diagram
  4. The options available to Android developers
  5. Estimate cost before you build
  6. Implementing model choice in code
  7. Evaluate quality with your own test set
  8. Worked examples
  9. Common mistakes
  10. Frequently asked questions
  11. Conclusion

Your team has decided to add an AI feature. Someone suggests "the best model", meaning the one at the top of a benchmark. Three months later the feature costs more than expected, feels slow on mobile networks, can't be used offline, and legal is asking where user data goes. None of that was the model's fault. It was a selection problem.

This guide is for intermediate Android developers and tech leads who need to choose a model, or a combination of models, for a real feature. You'll get a six-question framework, a decision diagram, a comparison of the main options available to Android developers, Kotlin code for routing between models at runtime, and a lightweight way to evaluate quality before you commit.

The principle: choose for the task, not the leaderboard

Benchmarks measure general capability on standard datasets. Your users care about one specific task on their devices and networks. For many mobile features, a smaller, faster or on-device model is the better product choice, even if it scores lower on a leaderboard.

Rule of thumb

Start with the smallest, cheapest, most private option that meets your quality bar on a realistic test set. Move up in size or to the cloud only when evidence shows you need to.

Six questions that decide the model

1. What kind of task is it?

  • Fixed perception task (read text, scan barcodes, detect objects or faces, identify language): use task-specific ML such as ML Kit or a LiteRT model. An LLM is the wrong tool.
  • Short text transformation (summarise, proofread, rewrite, describe an image): a small generative model, possibly Gemini Nano on-device.
  • Open-ended reasoning, long context, multi-turn chat, tool use: a cloud LLM.

2. How sensitive is the data?

Private messages, health notes and financial documents argue strongly for on-device processing, or at least explicit consent before sending data to a cloud provider. Remember that your Play Store Data safety declaration must match what you actually do.

3. How fast must it feel?

Inline features such as autocomplete or smart replies need near-instant responses. Network round-trips plus model time may be too slow, especially on mobile networks. Features where the user explicitly waits, such as "summarise this document", tolerate a few seconds, especially with streamed output.

4. Must it work offline?

If yes, only on-device options qualify: ML Kit, LiteRT, or Gemini Nano on supported devices.

5. Which devices must it support?

Gemini Nano runs only on specific supported devices. If the feature must work for all your users, including budget phones common in markets like India, you need a cloud path or a smaller model you ship yourself.

6. What can you afford per user, per month?

Cloud models are billed per token. On-device has no per-request fee but costs engineering effort and is limited by device and quota. Estimate cost before building, as shown below.

Decision diagram

Decision tree for choosing an AI model for an Android feature First question: is it a fixed perception task? If yes, use ML Kit or LiteRT. If no, must it work offline or keep data on device? If yes, check whether Gemini Nano supports the task and device: if yes use Gemini Nano via ML Kit GenAI, if no reconsider scope or ship a small LiteRT model. If no, does it need long context, chat or tools? If yes use a cloud model through Firebase AI Logic or your backend; if no use a hybrid of on-device first with cloud fallback. Fixed perception task? yes ML Kit / LiteRTfast, free, offline no Offline, or data muststay on device? yes Nano supports task+ target devices? yes no Gemini NanoML Kit GenAI Reduce scope or shipsmall LiteRT model no Long context, chat,tools or deep reasoning? yes Cloud modelFirebase AI Logic / backend no Hybridon-device โ†’ cloud
A starting point, not a rulebook. Cost and quality evaluation (below) can still change the answer.

The options available to Android developers

OptionPrivacyLatencyCostQuality ceilingDevice reach
ML Kit task APIsOn deviceVery lowNo per-call feeHigh for its fixed taskBroad
Custom LiteRT modelOn deviceLowEngineering + trainingDepends on your modelBroad (size-dependent)
Gemini Nano (ML Kit GenAI)On deviceLow, no networkNo per-call fee; per-app quotaGood for short, focused tasksSupported devices only
Cloud "Flash-Lite"-class modelLeaves deviceNetwork + fast modelLowest cloud price tierGood for simple tasksAll devices online
Cloud "Flash"-class modelLeaves deviceNetwork + fast modelModerateStrong general capabilityAll devices online
Cloud flagship reasoning modelLeaves deviceHigherHighestBest for complex reasoningAll devices online

Model families and names change frequently. At the time of writing, Google's documentation recommends its latest Flash and Flash-Lite models for new projects. Check the current models and pricing pages before you decide.

The same thinking applies if you compare providers, for example Gemini, OpenAI or open-weight models hosted on your own servers. Compare them on your task with your evaluation set, consider data-handling terms, and keep the provider behind an interface so you can switch. See Cloud AI vs On-Device AI for the deployment side of this choice.

Estimate cost before you build

Cloud LLM pricing is usually per million input tokens and per million output tokens, and output tokens often cost more. A token is roughly a few characters of English text. Estimate with your own numbers:

CostEstimate.ktKotlin
/**
 * Rough monthly cost estimate for a cloud AI feature.
 * Fill the prices from the provider's CURRENT pricing page; never hard-code guesses in production.
 */
data class CostInputs(
    val monthlyActiveUsers: Int,
    val requestsPerUserPerMonth: Double,
    val avgInputTokens: Int,          // prompt + context + chat history
    val avgOutputTokens: Int,
    val pricePerMillionInput: Double, // in your billing currency
    val pricePerMillionOutput: Double,
)

fun estimateMonthlyCost(c: CostInputs): Double {
    val requests = c.monthlyActiveUsers * c.requestsPerUserPerMonth
    val inputCost = requests * c.avgInputTokens / 1_000_000.0 * c.pricePerMillionInput
    val outputCost = requests * c.avgOutputTokens / 1_000_000.0 * c.pricePerMillionOutput
    return inputCost + outputCost
}

Two lessons usually come out of this exercise. First, input tokens dominate in chat, because the whole history is resent on every turn, so trimming or summarising history matters. Second, a small share of heavy users can dominate cost, so per-user limits are a product requirement, not an afterthought.

Implementing model choice in code

Treat the model as a replaceable dependency. Route each request based on capability, availability and user consent:

ModelRouter.ktKotlin
enum class AiTask { SUMMARIZE_SHORT, REWRITE, CHAT, LONG_DOCUMENT_QA }

interface AiEngine {
    val name: String
    suspend fun isAvailable(): Boolean
    fun supports(task: AiTask): Boolean
    suspend fun run(task: AiTask, input: String): String
}

class ModelRouter(
    private val onDevice: AiEngine,                   // e.g. Gemini Nano via ML Kit GenAI
    private val cloud: AiEngine,                      // e.g. Gemini via Firebase AI Logic
    private val cloudConsentGiven: () -> Boolean,     // user opted in to cloud processing
) {
    sealed interface Route {
        data class Use(val engine: AiEngine) : Route
        data class Unavailable(val reason: String) : Route
    }

    suspend fun route(task: AiTask): Route {
        if (onDevice.supports(task) && onDevice.isAvailable()) return Route.Use(onDevice)
        if (!cloud.supports(task)) return Route.Unavailable("Not supported on this device")
        if (!cloudConsentGiven()) return Route.Unavailable("Cloud processing is turned off")
        return if (cloud.isAvailable()) Route.Use(cloud) else Route.Unavailable("You're offline")
    }
}

The ViewModel calls route(), shows the reason when the result is Unavailable, and records which engine answered. That metric is invaluable when you investigate quality complaints later.

Evaluate quality with your own test set

Before committing to a model, build a small evaluation set: 30 to 100 realistic inputs, with notes on what a good output must contain. Run every candidate model over it and review the results, both manually and with simple automated checks.

EvalRunner.kt (JVM test or small script)Kotlin
data class EvalCase(val input: String, val mustMention: List<String>, val maxWords: Int)
data class EvalResult(val engine: String, val passed: Int, val total: Int, val avgMillis: Long)

suspend fun evaluate(engine: AiEngine, task: AiTask, cases: List<EvalCase>): EvalResult {
    var passed = 0
    var totalMillis = 0L
    for (case in cases) {
        val start = System.nanoTime()
        val output = runCatching { engine.run(task, case.input) }.getOrDefault("")
        totalMillis += (System.nanoTime() - start) / 1_000_000
        val words = output.split(Regex("\\s+")).count { it.isNotBlank() }
        val mentionsAll = case.mustMention.all { output.contains(it, ignoreCase = true) }
        if (output.isNotBlank() && mentionsAll && words <= case.maxWords) passed++
    }
    return EvalResult(engine.name, passed, cases.size, totalMillis / cases.size.coerceAtLeast(1))
}

Simple checks like these won't capture everything. Tone and factual accuracy still need human review, but they catch regressions fast, especially when a provider updates a model version.

Worked examples

Note-taking app: "Summarise this note"

Requirements
Private notes; short inputs; should work on the train with no signal.
Choice
Gemini Nano Summarization on supported devices; cloud fallback only with explicit opt-in.
Trade-off
Users on unsupported phones without opt-in don't get the feature.

E-commerce: product Q&A chat

Requirements
Answers grounded in the catalogue; multi-turn; all users.
Choice
Cloud Flash-class model behind your backend, with retrieval from the product database.
Trade-off
Per-token cost and backend work; needs rate limits.

Field inspection app: identify defects in photos

Requirements
Offline at remote sites; a specific set of defect types.
Choice
A custom image classifier trained on your images, deployed with LiteRT.
Trade-off
You must collect labelled data and maintain the model.

Common mistakes

  • Choosing by benchmark instead of by your own evaluation set.
  • Ignoring device reach. An on-device-only feature that most of your users can't access.
  • Hard-coding the model name in many places. Model names change, and older models get retired. Centralise it, ideally in remote config.
  • Not budgeting output tokens. Set a maximum output length, and ask for concise answers.
  • Forgetting the non-AI path. When no model is available, the app must still work.

Frequently asked questions

Is a bigger model always more accurate for my feature?

Not necessarily. For narrow tasks such as short summaries or rewriting, smaller models often perform well enough and respond faster at lower cost. Measure on your own test inputs.

Can I switch models later?

Yes, if the provider sits behind an interface and prompts are versioned. Re-run your evaluation set whenever you switch, because outputs will change.

How do I keep the model name updatable without an app release?

Store it in a remote configuration service such as Firebase Remote Config and validate it against an allow-list in the app or on your backend.

Should I fine-tune a model?

Usually not at first. Better prompts, examples in the prompt and retrieval of your own data (RAG) solve most problems more cheaply. Consider fine-tuning only when evaluation shows a consistent gap that prompting can't close.

Conclusion

Choosing an AI model for Android is a product and engineering decision: task fit, privacy, latency, offline needs, device reach and cost, verified with a realistic evaluation set. Start small and private, put the model behind an interface, route at runtime, and move up only when the data says you should.

Next step: write your feature's answers to the six questions and estimate its monthly cost with the formula above. Then dig into the deployment trade-offs in Cloud AI vs On-Device AI for Android.

Official references

๐Ÿ“ฑ Apps built by Yunok Tech

Real Android apps on Google Play, free to download.

See all our apps โ†’

Ready to build real Android applications?

Every AI feature still runs inside an Android app that has to be fast, reliable and well structured. Strengthen the Kotlin, Jetpack Compose and architecture skills that AI integrations depend on, then apply these AI concepts with confidence.

Move beyond theory and strengthen your Android development skills with Yunoktech's Android course. Learn core concepts, practical implementation, modern Android development techniques, and the reasoning behind building maintainable applications.

Explore the Android course and take your next step as an Android developer.

Share: LinkedIn X / Twitter WhatsApp