The `CompiledModel` API is the recommended interface for running machine
learning (ML) models with the [LiteRT in Google Play services](https://developers.google.com/edge/litert/android/play_services)
runtime. It runs your model on CPU or GPU through one API, without including the
LiteRT runtime in your APK.

You use the same `CompiledModel` and `TensorBuffer` classes as standalone LiteRT
(`com.google.ai.edge.litert`). Only the `Environment` instance comes from Google
Play services. For general information about the `CompiledModel` API, see the
[CompiledModel Kotlin API guide](https://developers.google.com/edge/litert/next/android_kotlin).

> [!NOTE]
> **Note:** If your app uses the older `Interpreter` API with Google Play services, see the [Interpreter Java API guide](https://developers.google.com/edge/litert/android/java).

## 1. Add project dependencies

Add the Google Play services LiteRT dependency to your app's `build.gradle`
file. This package pulls in `com.google.ai.edge.litert:litert-api` transitively,
so you do not need to declare `litert-api` separately.

    dependencies {
      ...
      // LiteRT CompiledModel API dependency for Google Play services, version
      // 17.0.0 or later
      implementation 'com.google.android.gms:play-services-litert:17.0.0'
      // Optional: For Kotlin coroutines Task.await() support
      implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.10.2'
      ...
    }

## 2. Initialize the LiteRT Environment

Initialize a LiteRT `Environment` from Google Play services using
`LiteRt.initialize(context)` *before* creating a `CompiledModel`:

### Kotlin

    import com.google.ai.edge.litert.Environment
    import com.google.android.gms.litert.LiteRt
    import kotlinx.coroutines.tasks.await
    ...
    // Initialize the Environment from Google Play services with an Android
    // context object.
    val env: Environment = LiteRt.initialize(context).await()

### Java

    import com.google.ai.edge.litert.Environment;
    import com.google.android.gms.litert.LiteRt;
    import com.google.android.gms.tasks.Task;
    ...
    // Initialize the Environment from Google Play services with an Android
    // context object.
    //
    // Callback pattern is recommended for Java to avoid blocking the thread.
    // Tasks.await() is used here for simplicity.
    Environment env = Tasks.await(LiteRt.initialize(context));

> [!NOTE]
> **Note:** Make sure the `LiteRt.initialize()` task completes before creating a `CompiledModel`. You can use `addOnSuccessListener()`, Kotlin coroutines `.await()`, or `Tasks.await()` on a background thread, as shown in the next section.

## 3. Create a CompiledModel and run inference (CPU)

Once the `Environment` is initialized, pass it to `CompiledModel.create()` along
with `CompiledModel.Options(Accelerator.CPU)` to load the model on the CPU, and
allocate input and output `TensorBuffer`s.

> [!IMPORTANT]
> **Important:** Create the `Environment`, `CompiledModel`, and `TensorBuffer`s once off the main thread and reuse them across inference calls (such as camera frames). Model compilation is expensive---do not recreate the `Environment` or `CompiledModel` on every `run()` call. Close these resources when they are no longer needed (for example, in `ViewModel.onCleared()` or `Activity.onDestroy()`).

### Kotlin

    import android.content.Context
    import com.google.ai.edge.litert.Accelerator
    import com.google.ai.edge.litert.CompiledModel
    import com.google.ai.edge.litert.Environment
    import com.google.ai.edge.litert.TensorBuffer
    import com.google.android.gms.litert.LiteRt
    import kotlinx.coroutines.tasks.await
    ...
    // 1. Initialize the Environment and CompiledModel once off the main thread
    val env: Environment = LiteRt.initialize(context).await()
    val model =
      CompiledModel.create(
        context.assets,
        "model.tflite",
        CompiledModel.Options(Accelerator.CPU),
        env,
      )
    val inputBuffers: List<TensorBuffer> = model.createInputBuffers()
    val outputBuffers: List<TensorBuffer> = model.createOutputBuffers()

    // 2. Run inference (reuse the compiled model and buffers across calls)
    inputBuffers[0].writeFloat(inputData)
    model.run(inputBuffers, outputBuffers)
    val output: FloatArray = outputBuffers[0].readFloat()

    // 3. Close resources when no longer needed
    inputBuffers.forEach { it.close() }
    outputBuffers.forEach { it.close() }
    model.close()
    env.close()

### Java

    import android.content.Context;
    import com.google.ai.edge.litert.Accelerator;
    import com.google.ai.edge.litert.CompiledModel;
    import com.google.ai.edge.litert.Environment;
    import com.google.ai.edge.litert.TensorBuffer;
    import com.google.android.gms.litert.LiteRt;
    import com.google.android.gms.tasks.Tasks;
    import java.util.List;
    ...
    // 1. Initialize the Environment and CompiledModel once off the main thread

    // Callback pattern is recommended for Java to avoid blocking the thread.
    // Tasks.await() is used here for simplicity.
    Environment env = Tasks.await(LiteRt.initialize(context));
    CompiledModel model =
        CompiledModel.create(
            context.getAssets(),
            "model.tflite",
            new CompiledModel.Options(Accelerator.CPU),
            env);
    List<TensorBuffer> inputBuffers = model.createInputBuffers();
    List<TensorBuffer> outputBuffers = model.createOutputBuffers();

    // 2. Run inference (reuse the compiled model and buffers across calls)
    inputBuffers.get(0).writeFloat(inputData);
    model.run(inputBuffers, outputBuffers);
    float[] output = outputBuffers.get(0).readFloat();

    // 3. Close resources when no longer needed
    for (TensorBuffer buffer : inputBuffers) {
      buffer.close();
    }
    for (TensorBuffer buffer : outputBuffers) {
      buffer.close();
    }
    model.close();
    env.close();

> [!WARNING]
> **Warning:** Do not call `Tasks.await()` on the foreground user interface thread because it blocks the UI thread and degrades the user experience. If you are on the main thread, use `environmentTask.addOnSuccessListener { ... }` or run initialization and inference inside a background coroutine or executor.

## 4. Hardware acceleration

With the `CompiledModel` API in Google Play services, you can accelerate model
inference across hardware accelerators:

- **CPU acceleration** : Supported by default (`Accelerator.CPU`).
- **GPU acceleration** : Supported on devices with a compatible GPU (`Accelerator.GPU`).
- **NPU acceleration** : Available in [standalone LiteRT](https://developers.google.com/edge/litert/next/npu); support in Google Play services is coming soon.

### GPU acceleration

LiteRT's GPU accelerator is built on the open-source
[ML Drift](https://github.com/google-ai-edge/ml-drift) engine. No extra
dependency is needed for GPU acceleration---the `play-services-litert` package
supports both CPU and GPU execution.

To use GPU acceleration with the `CompiledModel` API in Google Play services,
first enable GPU accelerator support in `LiteRtInitializationOptions` when
initializing the `Environment` with `LiteRt.initialize(context, initOptions)`:

### Kotlin

    import com.google.ai.edge.litert.Environment
    import com.google.android.gms.litert.LiteRt
    import com.google.android.gms.litert.LiteRtDsl.initializationOptions
    import kotlinx.coroutines.tasks.await
    ...
    val initOptions = initializationOptions {
      setEnableGpu(true)
    }
    val env: Environment = LiteRt.initialize(context, initOptions).await()

### Java

    import com.google.ai.edge.litert.Environment;
    import com.google.android.gms.litert.LiteRt;
    import com.google.android.gms.litert.client.LiteRtInitializationOptions;
    import com.google.android.gms.tasks.Task;
    ...
    LiteRtInitializationOptions initOptions =
        LiteRtInitializationOptions.builder()
            .setEnableGpu(true)
            .build();
    Task<Environment> environmentTask =
        LiteRt.initialize(context, initOptions);

Then create the `CompiledModel` with `Accelerator.GPU` and `Accelerator.CPU` to
`CompiledModel.Options` so that LiteRT automatically falls back to CPU execution
if GPU acceleration is unavailable on the device:

### Kotlin

    import com.google.ai.edge.litert.Accelerator
    import com.google.ai.edge.litert.CompiledModel
    ...
    // Specify GPU with CPU fallback if GPU is unavailable on the device
    val model =
      CompiledModel.create(
        context.assets,
        "model.tflite",
        CompiledModel.Options(Accelerator.GPU, Accelerator.CPU),
        env,
      )

### Java

    import com.google.ai.edge.litert.Accelerator;
    import com.google.ai.edge.litert.CompiledModel;
    import com.google.ai.edge.litert.Environment;
    import com.google.android.gms.tasks.Tasks;
    ...
    // Callback pattern is recommended for Java to avoid blocking the thread.
    // Tasks.await() is used here for simplicity.
    Environment env = Tasks.await(environmentTask);

    // Specify GPU with CPU fallback if GPU is unavailable on the device
    CompiledModel model =
        CompiledModel.create(
            context.getAssets(),
            "model.tflite",
            new CompiledModel.Options(Accelerator.GPU, Accelerator.CPU),
            env);

> [!NOTE]
> **Note:** You can also inspect whether the GPU accelerator is available in an initialized `Environment` by checking `env.getAvailableAccelerators().contains(Accelerator.GPU)`.

## Migrating from standalone LiteRT

> [!TIP]
> **Tip:** You can ask your coding agent to do this migration with the [LiteRT runtime skill](https://github.com/android/skills/tree/main/device-ai/litert/litert-runtime).

If you are migrating an existing app from standalone LiteRT to the Google Play
services runtime with the `CompiledModel` API, update your project using the
following steps:

1. Check that [LiteRT in Google Play services](https://developers.google.com/edge/litert/android/play_services) fits your app.
2. In your `build.gradle` file, remove the standalone LiteRT runtime
   dependencies (`com.google.ai.edge.litert:litert` and
   `com.google.ai.edge.litert:litert-gpu`) and add the Google Play services
   LiteRT dependency. This package provides the `com.google.ai.edge.litert` API
   classes (`CompiledModel`, `TensorBuffer`, `Environment`, and `Accelerator`)
   while loading the runtime dynamically from Google Play services to reduce
   your app size:

       dependencies {
           ...
           // Remove standalone LiteRT runtime dependencies:
           // implementation 'com.google.ai.edge.litert:litert:...'
           // implementation 'com.google.ai.edge.litert:litert-gpu:...'

           // Add the Google Play services LiteRT dependency:
           implementation 'com.google.android.gms:play-services-litert:17.0.0'
           ...
       }

3. Replace standalone `Environment.create()` calls (or `CompiledModel.create()`
   calls that omit the `Environment` parameter) with `LiteRt.initialize()` from
   `com.google.android.gms.litert.LiteRt`:

   - **For CPU inference** : Call `LiteRt.initialize(context)`.
   - **For GPU acceleration** : Configure `LiteRtInitializationOptions` with `setEnableGpu(true)` and call `LiteRt.initialize(context, initOptions)`.
4. Because `LiteRt.initialize()` is asynchronous and returns a
   `Task<Environment>`, wait for the task to complete (using Kotlin coroutines
   `.await()`, `addOnSuccessListener()`, or `Tasks.await()` on a background
   thread) and pass the initialized `Environment` explicitly to
   `CompiledModel.create()`.

5. Keep your buffer allocation and inference execution code unchanged. All
   other `CompiledModel` and `TensorBuffer` methods---such as
   `createInputBuffers()`, `createOutputBuffers()`, `writeFloat()`, `run()`,
   and `readFloat()`---work identically to standalone LiteRT.

The following example compares model initialization in standalone LiteRT with
the Google Play services runtime:

### Kotlin

    // Before (standalone LiteRT):
    // val env = Environment.create()
    // val model = CompiledModel.create(
    //   context.assets,
    //   "model.tflite",
    //   CompiledModel.Options(Accelerator.CPU),
    //   env,
    // )

    // After (Google Play services):
    val env = LiteRt.initialize(context).await()
    val model = CompiledModel.create(
      context.assets,
      "model.tflite",
      CompiledModel.Options(Accelerator.CPU),
      env,
    )

### Java

    // Before (standalone LiteRT):
    // Environment env = Environment.create();
    // CompiledModel model =
    //     CompiledModel.create(
    //         context.getAssets(),
    //         "model.tflite",
    //         new CompiledModel.Options(Accelerator.CPU),
    //         env);

    // After (Google Play services):
    // Callback pattern is recommended for Java to avoid blocking the thread.
    // Tasks.await() is used here for simplicity.
    Environment env = Tasks.await(LiteRt.initialize(context));
    CompiledModel model =
        CompiledModel.create(
            context.getAssets(),
            "model.tflite",
            new CompiledModel.Options(Accelerator.CPU),
            env);