This API is offered in beta, and is not subject to any SLA or deprecation policy. Changes may be made to this API that break backward compatibility.

To analyze a piece of text and extract the entities in it, invoke the
`annotate()` method and pass it either the text string or an instance of
`EntityExtractionParams` which can specify additional options such as a
reference time, timezone, or a filter to limit the search for a subset of entity
types. The API returns a list of `EntityAnnotation` objects containing
information about each entity.
This API supports on demand dynamic model downloads. See [this guide](https://developers.google.com/ml-kit/tips/installation-paths.md.txt) for more information.

| SDK Name | entity-extraction |
|---|---|
| Implementation | Assets for base detector are statically linked to your app at build time. |
| Asset Size Impact | Entity extraction has an app size impact of up to \~5.6MB. |

## Try it out

- Play around with [the sample app](https://github.com/googlesamples/mlkit/tree/master/android/entityextraction) to see an example usage of this API.

## Before you begin

> [!NOTE]
> This API requires Android API level 23 or above. Make sure that your app's build file uses a `minSdkVersion` value of 23 or higher.

1. In your project-level `build.gradle` file, make sure that Google's Maven repository is included in both the buildscript and allprojects sections.
2. Add the dependency for the ML Kit entity extraction library to your module's app-level gradle file, which is usually named `app/build.gradle`:

       dependencies {
       // ...

       implementation 'com.google.mlkit:entity-extraction:16.0.0-beta6'
       }

## Extract entities

Create an `EntityExtractor` object, and configure it with `EntityExtractorOptions`

### Kotlin

```kotlin
val entityExtractor =
   EntityExtraction.getClient(
       EntityExtractorOptions.Builder(EntityExtractorOptions.ENGLISH)
           .build())
```

### Java

```java
EntityExtractor entityExtractor =
        EntityExtraction.getClient(
            new EntityExtractorOptions.Builder(EntityExtractorOptions.ENGLISH)
                .build());
```

`EntityExtractorOptions` also accepts a user-defined `Executor` if you need, otherwise it will use default `Executor` in ML Kit

Ensure the required model has been downloaded to the device.

### Kotlin

```kotlin
entityExtractor
  .downloadModelIfNeeded()
  .addOnSuccessListener { _ ->
    /* Model downloading succeeded, you can call extraction API here. */
  }
  .addOnFailureListener { _ -> /* Model downloading failed. */ }
```

### Java

```java
entityExtractor
    .downloadModelIfNeeded()
    .addOnSuccessListener(
        aVoid -> {
          // Model downloading succeeded, you can call the extraction API here. 
        })
    .addOnFailureListener(
        exception -> {
          // Model downloading failed.
        });
```

After you confirm the model has been downloaded, pass a string or `EntityExtractionParams` to `annotate()`.
Don't call `annotate()` until you know the model is available.

### Kotlin

```kotlin
val params =
      EntityExtractionParams.Builder("My flight is LX373, please pick me up at 8am tomorrow.")
        .setEntityTypesFilter((/* optional entity type filter */)
        .setPreferredLocale(/* optional preferred locale */)
        .setReferenceTime(/* optional reference date-time */)
        .setReferenceTimeZone(/* optional reference timezone */)
        .build()
entityExtractor
      .annotate(params)
      .addOnSuccessListener {
        // Annotation process was successful, you can parse the EntityAnnotations list here.
      }
      .addOnFailureListener {
        // Check failure message here.
      }
```

### Java

```java
EntityExtractionParams params = new EntityExtractionParams
        .Builder("My flight is LX373, please pick me up at 8am tomorrow.")
        .setEntityTypesFilter(/* optional entity type filter */)
        .setPreferredLocale(/* optional preferred locale */)
        .setReferenceTime(/* optional reference date-time */)
        .setReferenceTimeZone(/* optional reference timezone */)
        .build();
entityExtractor
        .annotate(params)
        .addOnSuccessListener(new OnSuccessListener<List<EntityAnnotation>>() {
          @Override
          public void onSuccess(List<EntityAnnotation> entityAnnotations) {
            // Annotation process was successful, you can parse the EntityAnnotations list here.
          }
        })
        .addOnFailureListener(new OnFailureListener() {
          @Override
          public void onFailure(@NonNull Exception e) {
            // Check failure message here.
          }
        });
```

`PreferredLocale`, `ReferenceTime` and `ReferenceTimeZone` will only influence
DateTime entities. If these are not explicitly set, they default to values
from the user's device.

Loop over the annotation results to retrieve information about the
recognized entities.

### Kotlin

```kotlin
for (entityAnnotation in entityAnnotations) {
  val entities: List<Entity> = entityAnnotation.entities

  Log.d(TAG, "Range: ${entityAnnotation.start} - ${entityAnnotation.end}")
  for (entity in entities) {
    when (entity) {
      is DateTimeEntity -> {
        Log.d(TAG, "Granularity: ${entity.dateTimeGranularity}")
        Log.d(TAG, "TimeStamp: ${entity.timestampMillis}")
      }
      is FlightNumberEntity -> {
        Log.d(TAG, "Airline Code: ${entity.airlineCode}")
        Log.d(TAG, "Flight number: ${entity.flightNumber}")
      }
      is MoneyEntity -> {
        Log.d(TAG, "Currency: ${entity.unnormalizedCurrency}")
        Log.d(TAG, "Integer part: ${entity.integerPart}")
        Log.d(TAG, "Fractional Part: ${entity.fractionalPart}")
      }
      else -> {
        Log.d(TAG, "  $entity")
      }
    }
  }
}
```

### Java

```java
List<EntityAnnotation> entityAnnotations = /* Get from EntityExtractor */;
for (EntityAnnotation entityAnnotation : entityAnnotations) {
  List<Entity> entities = entityAnnotation.getEntities();

  Log.d(TAG, String.format("Range: [%d, %d)", entityAnnotation.getStart(), entityAnnotation.getEnd()));
  for (Entity entity : entities) {
    switch (entity.getType()) {
      case Entity.TYPE_DATE_TIME:
        DateTimeEntity dateTimeEntity = entity.asDateTimeEntity();
        Log.d(TAG, "Granularity: " + dateTimeEntity.getDateTimeGranularity());
        Log.d(TAG, "Timestamp: " + dateTimeEntity.getTimestampMillis());
      case Entity.TYPE_FLIGHT_NUMBER:
        FlightNumberEntity flightNumberEntity = entity.asFlightNumberEntity();
        Log.d(TAG, "Airline Code: " + flightNumberEntity.getAirlineCode());
        Log.d(TAG, "Flight number: " + flightNumberEntity.getFlightNumber());
      case Entity.TYPE_MONEY:
        MoneyEntity moneyEntity = entity.asMoneyEntity();
        Log.d(TAG, "Currency: " + moneyEntity.getUnnormalizedCurrency());
        Log.d(TAG, "Integer Part: " + moneyEntity.getIntegerPart());
        Log.d(TAG, "Fractional Part: " + moneyEntity.getFractionalPart());
      case Entity.TYPE_UNKNOWN:
      default:
        Log.d(TAG, "Entity: " + entity);
    }
  }
}
```

Call the `close()` method when you no longer need the `EntityExtractor` object. If you are using `EntityExtractor` in a Fragment or AppCompatActivity, you can call [LifecycleOwner.getLifecycle()](https://developer.android.com/reference/androidx/lifecycle/LifecycleOwner#getLifecycle()) on the Fragment or AppCompatActivity, and then [Lifecycle.addObserver](https://developer.android.com/reference/androidx/lifecycle/Lifecycle#addObserver(androidx.lifecycle.LifecycleObserver)). For example:

### Kotlin

```kotlin
val options = ...
val extractor = EntityExtraction.getClient(options);
getLifecycle().addObserver(extractor);
```

### Java

```java
EntityExtractorOptions options = ...
EntityExtractor extractor = EntityExtraction.getClient(options);
getLifecycle().addObserver(extractor);
```

## Explicitly manage entity extraction models

When you use the entity extraction API as described above, ML Kit automatically downloads language specific models to the device as required (when you call `downloadModelIfNeeded()`). You can also explicitly manage the models you want available on the device by using ML Kit's model management API. This can be useful if you want to download models ahead of time. The API also allows you to delete models that are no longer required.

### Kotlin

```kotlin
val modelManager = RemoteModelManager.getInstance()

// Get entity extraction models stored on the device.
modelManager.getDownloadedModels(EntityExtractionRemoteModel::class.java)
  .addOnSuccessListener {
    // ...
  }
  .addOnFailureListener({
    // Error.
  })
    
// Delete the German model if it's on the device.
val germanModel =
  EntityExtractionRemoteModel.Builder(EntityExtractorOptions.GERMAN).build()
modelManager.deleteDownloadedModel(germanModel)
  .addOnSuccessListener({
    // Model deleted.
  })
  .addOnFailureListener({
    // Error.
  })
    
// Download the French model.
val frenchModel =
  EntityExtractionRemoteModel.Builder(EntityExtractorOptions.FRENCH).build()
val conditions =
  DownloadConditions.Builder()
    .requireWifi()
    .build()
modelManager.download(frenchModel, conditions)
  .addOnSuccessListener({
    // Model downloaded.
  })
  .addOnFailureListener({
    // Error.
  })
```

### Java

```java
// Get entity extraction models stored on the device.
modelManager.getDownloadedModels(EntityExtractionRemoteModel.class)
    .addOnSuccessListener(new OnSuccessListener<Set<EntityExtractionRemoteModel>>() {
      @Override
      public void onSuccess(Set<EntityExtractionRemoteModel> models) {
        // ...
      }
    })
    .addOnFailureListener(new OnFailureListener() {
      @Override
      public void onFailure(@NonNull Exception e) {
        // Error.
      }
    });

// Delete the German model if it's on the device.
EntityExtractionRemoteModel germanModel = new EntityExtractionRemoteModel.Builder(EntityExtractorOptions.GERMAN).build();
    modelManager.deleteDownloadedModel(germanModel)
        .addOnSuccessListener(new OnSuccessListener<Void>() {
          @Override
          public void onSuccess(Void v) {
            // Model deleted.
          }
        })
        .addOnFailureListener(new OnFailureListener() {
          @Override
          public void onFailure(@NonNull Exception e) {
            // Error.
          }
        });

// Download the French model.
EntityExtractionRemoteModel frenchModel = new EntityExtractionRemoteModel.Builder(EntityExtractorOptions.FRENCH).build();
    DownloadConditions conditions = new DownloadConditions.Builder()
        .requireWifi()
        .build();
    modelManager.download(frenchModel, conditions)
        .addOnSuccessListener(new OnSuccessListener<Void>() {
          @Override
          public void onSuccess(Void v) {
            // Model downloaded.
          }
        })
        .addOnFailureListener(new OnFailureListener() {
          @Override
          public void onFailure(@NonNull Exception e) {
            // Error.
          }
        });
```