Complication data sources expose information to watch face
[complications](https://developer.android.com/training/wearables/watch-faces/complications),
supplying text, images, and numbers that the watch face can render.

A data source service extends
[`SuspendingComplicationDataSourceService`](https://developer.android.com/reference/kotlin/androidx/wear/watchface/complications/datasource/SuspendingComplicationDataSourceService) to deliver useful
information directly to a watch face.

## Getting started

Add the following dependency to your app module:

```kotlin
dependencies {
  implementiation("androidx.wear.watchface:watchface-complications-data-source-ktx:1.2.1")
}
```

<br />

## Create the data source service

When complication data is needed, the Wear OS system sends update requests to your data source.
To respond to the update requests, your data source must implement the
[`onComplicationRequest()`](https://developer.android.com/reference/kotlin/androidx/wear/watchface/complications/datasource/SuspendingComplicationDataSourceService#onComplicationRequest(androidx.wear.watchface.complications.datasource.ComplicationRequest)) method of the `SuspendingComplicationDataSourceService`
class.

The Wear OS system calls `onComplicationRequest()` when it needs data from your
source---for example, when a complication using your data source becomes active or when a
fixed amount of time passes.

**Note:** When your data source provides data, the watch face
receives the raw values. The watch face is responsible for formatting the data for display.

The following code snippet shows a sample implementation:  

```kotlin
class MyComplicationDataSourceService : SuspendingComplicationDataSourceService() {
    override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData? {
        // Retrieve the latest info for inclusion in the data.
        val text = getLatestData()
        return shortTextComplicationData(text)
    }

    override fun getPreviewData(type: ComplicationType): ComplicationData? {
        return shortTextComplicationData("Event 1")
    }

    private fun shortTextComplicationData(text: String) =
        ShortTextComplicationData.Builder(
            text = PlainComplicationText.Builder(text).build(),
            contentDescription = PlainComplicationText.Builder(text).build()
        )
            // Add further optional details here such as icon, tap action, and title.
            .build()

    // ...
}
```

## Manifest declarations and permissions


Data sources must include specific declarations in their app manifest to be treated as
a data source by the Android system. This section explains the required settings for
data sources.


In your app's manifest, declare the service and add an update request action intent filter.
The manifest must also protect the service by adding the `BIND_COMPLICATION_PROVIDER`
permission to ensure that only the Wear OS system can bind to provider services.


Also, include an `android:icon` attribute in the
`service` element that provides a
single-color white icon. We recommend vector drawables for the icons.
The icon represents the data source and is shown in the complication picker.


Here's an example:  

```xml
<service
    android:name=".snippets.complication.MyComplicationDataSourceService"
    android:exported="true"
    android:label="@string/my_complication_service_label"
    android:icon="@drawable/complication_icon"
    android:permission="com.google.android.wearable.permission.BIND_COMPLICATION_PROVIDER">
    <intent-filter>
        <action android:name="android.support.wearable.complications.ACTION_COMPLICATION_UPDATE_REQUEST" />
    </intent-filter>

    <!-- Supported types should be comma-separated, for example: "SHORT_TEXT,SMALL_IMAGE" -->
    <meta-data
        android:name="android.support.wearable.complications.SUPPORTED_TYPES"
        android:value="SHORT_TEXT" />
    <meta-data
        android:name="android.support.wearable.complications.UPDATE_PERIOD_SECONDS"
        android:value="300" />

    <!-- Optionally, specify a configuration activity, where the user can configure your complication. -->
    <meta-data
        android:name="android.support.wearable.complications.PROVIDER_CONFIG_ACTION"
        android:value="MY_CONFIG_ACTION" />

</service>
```

### Metadata elements


In your manifest file, notice the following metadata elements:

- `android:name="android.support.wearable.complications.SUPPORTED_TYPES"`: Specifies the types of complication data that the data source supports.
- `android:name="android.support.wearable.complications.UPDATE_PERIOD_SECONDS"`: Specifies how often the system should check for updates to the data.


When your complication data data source is active,
`UPDATE_PERIOD_SECONDS` specifies how often you want the
system to check for updates to the data. If the information shown in the
complication doesn't need to update on a regular schedule, such as when
you're [using push updates](https://developer.android.com/training/wearables/complications/exposing-data#push-updates), set this value to
`0`.


If you don't set `UPDATE_PERIOD_SECONDS` to `0`,
you must use a value of at least `300` (5 minutes), which is
the minimum update period that the system enforces, to preserve
device battery life. In addition, keep in mind that update requests
come less often when the device is in ambient mode or isn't being worn.

### Add a configuration activity


If required, a data source can include a configuration activity that is
shown to the user when the user chooses that particularly data source from the
complication picker. For example, a world clock data source might have a configuration
activity that allows the user to choose the city or time zone to display.


The example manifest includes a `meta-data` element with the
`PROVIDER_CONFIG_ACTION` key. The value of this element is the action that is used
to launch the configuration activity.


Create the configuration activity, and add an intent filter that matches the action for it in
your manifest file.  

```xml
<intent-filter>
    <action android:name="MY_CONFIG_ACTION" />
    <category android:name="android.support.wearable.complications.category.PROVIDER_CONFIG" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
```


The activity can obtain details of the complication slot it is configuring from the intent
within the `onCreate()` method of the activity:  

```kotlin
// Keys defined on ComplicationDataSourceService
val id = intent.getIntExtra(EXTRA_CONFIG_COMPLICATION_ID, -1)
val type = intent.getIntExtra(EXTRA_CONFIG_COMPLICATION_TYPE, -1)
val source = intent.getStringExtra(EXTRA_CONFIG_DATA_SOURCE_COMPONENT)
```

The configuration activity must reside in the same package as the
provider. The configuration activity must return `RESULT_OK` or
`RESULT_CANCELED` to tell the system whether the data source
should be set:  

```kotlin
setResult(RESULT_OK) // Or RESULT_CANCELED to cancel configuration
finish()
```

## Use push updates


As an alternative to specifying an update interval in your app's manifest, you can use an instance of
[`ComplicationDataSourceUpdateRequester`](https://developer.android.com/reference/androidx/wear/watchface/complications/datasource/ComplicationDataSourceUpdateRequester) to initiate updates dynamically.
To request an update, call `requestUpdate()`.

**Caution:** To preserve device battery life,
don't call `requestUpdate()` from your instance of
`ComplicationDataSourceUpdateRequester` more often than every 5 minutes on
average.

## Provide time-dependent values


Some complications need to display a value that relates to the current
time. Examples include the current date, the time until the next meeting,
or the time in another time zone.


Don't update a complication every
second or minute to keep those values up to date. Instead, specify
the values as relative to the current date or time using time-dependent text. The following
classes allow you to create these time-dependent values:

- [`TimeFormatComplicationText`](https://developer.android.com/reference/androidx/wear/watchface/complications/data/TimeFormatComplicationText) - formats a date or time value.
- [`TimeDifferenceComplicationText`](https://developer.android.com/reference/androidx/wear/watchface/complications/data/TimeDifferenceComplicationText) - counts up or down to a specified time.

## Timeline data


For complication data sources that provide a sequence of values at pre-defined times, use
[`SuspendingTimelineComplicationDataSourceService`](https://developer.android.com/reference/androidx/wear/watchface/complications/datasource/SuspendingTimelineComplicationDataSourceService).


An example of this would be a "next event" data source from a calendar app:
Instead of the system having to poll the data source regularly for the next
event, the data source can provide a timeline of events once, and then the
data source can initiate updates if the calendar changes. This minimizes the
load on the system and lets the complication show the correct event in a
timely manner:  

```kotlin
class MyTimelineComplicationDataSourceService : SuspendingTimelineComplicationDataSourceService() {
    override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationDataTimeline? {
        if (request.complicationType != ComplicationType.SHORT_TEXT) {
            return ComplicationDataTimeline(
                defaultComplicationData = NoDataComplicationData(),
                timelineEntries = emptyList()
            )
        }
        // Retrieve list of events from your own datasource / database.
        val events = getCalendarEvents()
        return ComplicationDataTimeline(
            defaultComplicationData = shortTextComplicationData("No event"),
            timelineEntries = events.map {
                TimelineEntry(
                    validity = TimeInterval(it.start, it.end),
                    complicationData = shortTextComplicationData(it.name)
                )
            }
        )
    }

    override fun getPreviewData(type: ComplicationType): ComplicationData? {
        return shortTextComplicationData("Event 1")
    }

    private fun shortTextComplicationData(text: String) =
        ShortTextComplicationData.Builder(
            text = PlainComplicationText.Builder(text).build(),
            contentDescription = PlainComplicationText.Builder(text).build()
        )
            // Add further optional details here such as icon, tap action, title etc
            .build()

    // ...
}
```


The behavior of the `SuspendingTimelineComplicationDataSourceService` is as follows:

- When the current time falls within the start and end time of an entry in the timeline, the watch face uses that value.
- When the current time doesn't fall within any entry in the timeline, the default value is used. For example, in the calendar app, this could be "No event."
- If the current time falls within multiple events, the shortest event is used.

<br />

## Provide dynamic values


Starting in Wear OS 4, some complications can display values that refresh more frequently
based on values that are available directly to the platform. To provide this capability in
your complications, use
[`ComplicationData`](https://developer.android.com/reference/androidx/wear/watchface/complications/data/ComplicationData) fields that accept
[dynamic values](https://developer.android.com/training/wearables/data/dynamic). The platform evaluates and
updates these values frequently, without requiring the complication provider to be running.


Example fields include
[`GoalProgressComplicationData`'s dynamic value field](https://developer.android.com/reference/androidx/wear/watchface/complications/data/GoalProgressComplicationData#getDynamicValue()), and
[`DynamicComplicationText`](https://developer.android.com/reference/androidx/wear/watchface/complications/data/DynamicComplicationText), which can be used in any
[`ComplicationText`](https://developer.android.com/reference/androidx/wear/watchface/complications/data/ComplicationText) field. These dynamic values are based on the
[`androidx.wear.protolayout.expression`](https://developer.android.com/reference/androidx/wear/protolayout/expression/package-summary) library.


In certain situations, the platform cannot evaluate dynamic values:

- **Dynamic value is sometimes not available:** This happens, for example, when the device is off-wrist. In these situations, the platform uses the value of the [dynamic value invalidation fallback field](https://developer.android.com/reference/androidx/wear/watchface/complications/data/ComplicationData#getDynamicValueInvalidationFallback()) instead, in a [`NoDataComplicationData`'s placeholder field](https://developer.android.com/reference/androidx/wear/watchface/complications/data/NoDataComplicationData#getPlaceholder()).
- **Dynamic value is never available:** This happens on a device that is running on an older release of Wear OS 4. In this situation, the platform uses a companion fallback field, such as [getFallbackValue](https://developer.android.com/reference/androidx/wear/watchface/complications/data/DynamicComplicationText#getFallbackValue())`()`.

## Related resources

- [Types and fields](https://developer.android.com/training/wearables/watch-faces/adding-complications#types-fields)  
- [Wear OS samples repository](https://github.com/android/wear-os-samples)