Expose data to complications

Stay organized with collections Save and categorize content based on your preferences.

Data provider apps expose information to watch face complications, supplying fields that contain text, strings, images, and numbers.

A data provider service extends ComplicationProviderService to deliver useful information directly to a watch face.

Create a data provider project

To create a project in Android Studio for your data provider app:

  1. Click File > New > New project.
  2. In the Project Template window, click the Wear OS tab, select No Activity, and click Next.
  3. In the Configure Your Project window, name your project, fill out the standard project information, and click Finish.
  4. Android Studio creates a project with an app module for your data provider. For more information about projects in Android Studio, see Create a project.
  5. Begin your data provider app by creating a new class that extends BroadcastReceiver. The purpose of that class is to listen for complication update requests from the Wear OS system. Additionally, create a new class that extends ComplicationProviderService in order to actually provide data as requested by appropriate complications. For more information, see the following:

    Note: Adding an activity for your data provider is optional. You may want to add an activity that launches only when a user taps a complication, for example.

Implement a method for update requests

When complication data is needed, the Wear OS system sends update requests to your data provider. The requests are received by your BroadcastReceiver. To respond to the update requests, your data provider must implement the onComplicationUpdate() method of the ComplicationProviderService class. The Wear OS system calls this method when data is needed from your provider, for example when a complication using your provider becomes active, or when a fixed amount of time has passed. A ComplicationManager object is passed as a parameter to the onComplicationUpdate method, and can be used to send data back to the system.

Note: When your data provider app provides data, the watch face receives the raw values that you send, so the watch face can draw the information.

The following code snippet shows a sample implementation of the onComplicationUpdate method:


override fun onComplicationUpdate(
    complicationId: Int, dataType: Int, complicationManager: ComplicationManager) {

    Log.d(TAG, "onComplicationUpdate() id: $complicationId")

    // Used to create a unique key to use with SharedPreferences for this complication.
    val thisProvider = ComponentName(this, javaClass)

    // Retrieves your data, in this case, we grab an incrementing number from SharedPrefs.
    val preferences = getSharedPreferences(ComplicationTapBroadcastReceiver.COMPLICATION_PROVIDER_PREFERENCES_FILE_KEY, 0)

    val number = preferences.getInt(
                    thisProvider, complicationId),
    val numberText = String.format(Locale.getDefault(), "%d!", number)

    var complicationData: ComplicationData? = null

    when (dataType) {
        ComplicationData.TYPE_SHORT_TEXT -> complicationData = ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
        else -> if (Log.isLoggable(TAG, Log.WARN)) {
                    Log.w(TAG, "Unexpected complication type $dataType")

    if (complicationData != null) {
        complicationManager.updateComplicationData(complicationId, complicationData)
    } else {
        // If no data is sent, we still need to inform the ComplicationManager, so
        // the update job can finish and the wake lock isn't held any longer.


public void onComplicationUpdate(
       int complicationId, int dataType, ComplicationManager complicationManager) {

   Log.d(TAG, "onComplicationUpdate() id: " + complicationId);

   // Used to create a unique key to use with SharedPreferences for this complication.
   ComponentName thisProvider = new ComponentName(this, getClass());

   // Retrieves your data, in this case, we grab an incrementing number from SharedPrefs.
   SharedPreferences preferences =
     getSharedPreferences( ComplicationTapBroadcastReceiver.COMPLICATION_PROVIDER_PREFERENCES_FILE_KEY, 0);

   int number =
                           thisProvider, complicationId),
   String numberText = String.format(Locale.getDefault(), "%d!", number);

   ComplicationData complicationData = null;

   switch (dataType) {
       case ComplicationData.TYPE_SHORT_TEXT:
           complicationData =
                   new ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
           if (Log.isLoggable(TAG, Log.WARN)) {
               Log.w(TAG, "Unexpected complication type " + dataType);

   if (complicationData != null) {
       complicationManager.updateComplicationData(complicationId, complicationData);

   } else {
       // If no data is sent, we still need to inform the ComplicationManager, so
       // the update job can finish and the wake lock isn't held any longer.

Manifest declarations and permissions

Data provider apps must include specific declarations in their app manifest to be treated as a data provider by the Android system. This section explains the required settings for data provider apps. 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.

In addition, within the service element, you must include an android:icon attribute. The provided icon should be a single-color white icon. Vector drawables are recommended for the icons. An icon should represent the provider and will be shown in the provider chooser.

Here's an example:


Specify the meta data elements

In your manifest file, include metadata to specify the supported types, update period, and configuration action, as shown in the following example:

    android:value="RANGED_VALUE,SHORT_TEXT,LONG_TEXT" />

    android:value="300" />

When your complication data provider 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, 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 in order to preserve device battery life. In addition, keep in mind that update requests may come less often when the device is in ambient mode or isn't being worn.

For more details on sending updates, see the keys listed for the ComplicationProviderService class in the Wear OS API Reference.

Add a configuration activity

If required, a provider can include a configuration activity that is shown to the user when the user chooses a data provider. To include the configuration activity, include a metadata item in the provider service declaration in the manifest with a key of the following:


The value can be an action of your choice.

Then create the configuration activity with an intent filter for that action. 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 provider should be set.

Provider-specified safe watch faces

Providers can specify certain watch faces as "safe" to receive their data. This is intended to be used only when a watch face attempts to use the provider as a default (see the following section), and the provider trusts the watch face app.

To declare watch faces as safe, the provider adds metadata with a key of android.support.wearable.complications.SAFE_WATCH_FACES. The metadata value should be a comma-separated list (whitespace is ignored). Entries in the list can be component names (of WatchFaceServices, given as if ComponentName.flattenToString() had been called), or they can be package names (of apps, in which case every watch face within a specified app is considered safe). For example:


Provide burn-in safe images

On screens susceptible to burn-in, solid blocks of color should be avoided in ambient mode. If your icons or images include solid blocks of color, you should also provide a burn-in safe version.

When you provide an icon using ComplicationData.Builder#setIcon, include a burn-in safe version using ComplicationData.Builder#setBurnInProtectionIcon.

When you provide an image using ComplicationData.Builder#setSmallImage, include a burn-in safe version using ComplicationData.Builder#setBurnInProtectionSmallImage.

Use push updates

As an alternative to specifying a constant, nonzero update interval for a complication in your app's manifest, you can use an instance of ProviderUpdateRequester to request updates dynamically. To request an update to the complication's user-visible content, call onComplicationUpdate().

Caution: To preserve device battery life, your instance of ProviderUpdateRequester shouldn't call onComplicationUpdate() 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; a complication should never need to update that often. Instead, specify the values as relative to the current date or time using time-dependent text. You can use builders in the ComplicationText class to create these time-dependent values.

Complication update rate

You may want to update complications at a rapid rate. However, this might impact the battery life of the device. You can choose to use a privileged Complication request API that allows specific complications to update more frequently. Use of this API requires allowlisting by the watch manufacturer. Each watch manufacturer decides which complications can update at a faster rate than usually permitted.