TensorFlow
Android development
machine learning mobile
TensorFlow Lite
AI on Android

How to work with Tensorflow on Android platform?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

If you want to run machine learning on Android today, the practical answer is usually TensorFlow Lite, not the older full TensorFlow Android integration. The workflow is straightforward once you separate it into model conversion, packaging, inference code, and on-device performance tuning.

Use TensorFlow Lite, Not Full TensorFlow

Older blog posts often mention the original TensorFlow Mobile libraries, but those are not the normal choice anymore. For Android inference, tflite gives you:

  • smaller binaries
  • faster startup
  • delegate support for GPU and NNAPI
  • easier packaging inside an app

The standard flow is:

  1. Train or obtain a TensorFlow model.
  2. Convert it to .tflite.
  3. Ship the file in the Android app.
  4. Run inference with the Interpreter API.

Convert the Model First

You normally convert the model on a desktop machine, not on the phone.

python
1import tensorflow as tf
2
3model = tf.keras.Sequential([
4    tf.keras.layers.Input(shape=(4,)),
5    tf.keras.layers.Dense(16, activation="relu"),
6    tf.keras.layers.Dense(3, activation="softmax"),
7])
8
9converter = tf.lite.TFLiteConverter.from_keras_model(model)
10tflite_model = converter.convert()
11
12with open("model.tflite", "wb") as f:
13    f.write(tflite_model)

If the model is too large or slow, quantization is usually the next step. That reduces size and can improve inference speed.

python
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_model = converter.convert()

Do the conversion once as part of your build or release pipeline, not at app startup.

Add the Android Dependency

In a modern Android project, add the TensorFlow Lite dependency in Gradle.

kotlin
dependencies {
    implementation("org.tensorflow:tensorflow-lite:2.14.0")
}

If you need GPU or support helpers, add those explicitly rather than pulling in everything by default.

kotlin
1dependencies {
2    implementation("org.tensorflow:tensorflow-lite-gpu:2.14.0")
3    implementation("org.tensorflow:tensorflow-lite-support:0.4.4")
4}

Keep versions aligned. Mixing random library versions is a common source of startup failures.

Load the Model from Assets

The model file usually lives under src/main/assets. Memory-map it instead of reading it into a plain byte array.

kotlin
1import android.content.Context
2import org.tensorflow.lite.Interpreter
3import java.io.FileInputStream
4import java.nio.MappedByteBuffer
5import java.nio.channels.FileChannel
6
7fun loadModelFile(context: Context, fileName: String): MappedByteBuffer {
8    val fileDescriptor = context.assets.openFd(fileName)
9    FileInputStream(fileDescriptor.fileDescriptor).use { input ->
10        val channel = input.channel
11        return channel.map(
12            FileChannel.MapMode.READ_ONLY,
13            fileDescriptor.startOffset,
14            fileDescriptor.declaredLength
15        )
16    }
17}
18
19val options = Interpreter.Options().apply {
20    setNumThreads(4)
21}
22
23val interpreter = Interpreter(loadModelFile(context, "model.tflite"), options)

This is the baseline integration for local inference.

Match Input and Output Shapes Exactly

Most Android TensorFlow issues are not Android issues at all. They are shape, dtype, or preprocessing mismatches.

kotlin
1val input = Array(1) { FloatArray(4) }
2input[0][0] = 0.1f
3input[0][1] = 0.4f
4input[0][2] = 0.2f
5input[0][3] = 0.8f
6
7val output = Array(1) { FloatArray(3) }
8interpreter.run(input, output)
9
10println(output[0].joinToString())

The shape and element type must match what the model expects. If training used normalized image pixels or tokenized text, Android inference must use the same preprocessing rules.

Keep Preprocessing Consistent

For image models, the typical flow is:

  1. resize the bitmap
  2. convert pixels into the expected numeric format
  3. normalize exactly as training did

If the model was trained on values in the range from zero to one, passing raw values in the range from zero to 255 will produce bad predictions even though the app does not crash.

That is why model integration should include a small test vector with a known expected output. It is the fastest way to catch preprocessing drift.

Performance Tuning on Device

Start with the CPU interpreter and basic correctness. After that, tune:

  • 'setNumThreads'
  • quantized model variants
  • GPU delegate
  • NNAPI delegate

Do not assume the GPU path is always faster. On smaller models, delegate overhead can cancel out the benefit. Measure latency on the actual target devices.

If startup time matters, create the interpreter once and reuse it instead of rebuilding it for every button tap.

Debugging Strategy

When inference fails, check these items first:

  • model file is packaged in assets
  • dependency versions are compatible
  • input tensor shape matches model
  • preprocessing matches training
  • output buffer shape matches model output

A quick command during development is still useful:

bash
adb logcat | grep -i tflite

That will often reveal missing assets, unsupported ops, or delegate initialization failures.

Common Pitfalls

  • Using outdated TensorFlow Mobile examples instead of TensorFlow Lite.
  • Loading the model correctly but feeding the wrong input shape or dtype.
  • Forgetting to reproduce training-time preprocessing on Android.
  • Recreating the interpreter for every inference call.
  • Enabling delegates before basic CPU inference is known to work.

Summary

  • For Android inference, start with TensorFlow Lite.
  • Convert the model ahead of time and ship the .tflite file in assets.
  • Load the model with a memory-mapped file and run inference through Interpreter.
  • Treat preprocessing and tensor shapes as part of the model contract.
  • Verify correctness on CPU first, then optimize with threads or delegates.

Course illustration
Course illustration

All Rights Reserved.