A watch face complication displays data that is supplied by a data provider. Data providers supply raw fields containing text, strings, images and numbers to watch faces.
A data provider service extends
ComplicationProviderService
to deliver users useful information directly
to the watch face.
Refer to the following related resources:
Create data provider apps
Wear OS by Google sends update requests to data provider apps when there is a need to update the complication data.
To respond to update requests from the system, your data provider app must implement the
onComplicationUpdate()
method of the ComplicationProviderService
class. This method will be
called when the system wants data from your provider - this could be 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 you provide data as a complication data provider, the watch face receives the raw values you send so it can draw them on the watch face.
The following code snippet shows a sample implementation of the
onComplicationUpdate
method:
Kotlin
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: Int = preferences.getInt( ComplicationTapBroadcastReceiver.getPreferenceKey(thisProvider, complicationId), 0 ) val numberText = String.format(Locale.getDefault(), "%d!", number) when (dataType) { ComplicationData.TYPE_SHORT_TEXT -> ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT) .setShortText(ComplicationText.plainText(numberText)) .build().also { complicationData -> complicationManager.updateComplicationData(complicationId, complicationData) } else -> { if (Log.isLoggable(TAG, Log.WARN)) { Log.w(TAG, "Unexpected complication type $dataType") } // 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. complicationManager.noUpdateRequired(complicationId) } } }
Java
@Override 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 = preferences.getInt( ComplicationTapBroadcastReceiver.getPreferenceKey( thisProvider, complicationId), 0); 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) .setShortText(ComplicationText.plainText(numberText)) .build(); break; default: 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. complicationManager.noUpdateRequired(complicationId); } }
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:
<service android:name=".provider.IncrementingNumberComplicationProviderService" android:icon="@drawable/icn_complications" android:label="@string/complications_provider_incrementing_number" 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> </service>
Specify the meta data elements
In your manifest file, include metadata to specify the supported types, update period, and
configuration action, if required; for details,
see the keys listed for the
ComplicationProviderService
class
in the
Wear API Reference.
When your complication data provider is active, UPDATE_PERIOD_SECONDS
specifies
how often you want the system to check for updates to the data. This should be set to as long
a time as possible, or to 0 when scheduled updates are not required, as updating too
frequently may impact battery life. Note that update requests are not guaranteed to be sent
with this frequency. The system applies a minimum update period of 300 seconds, and in
particular, update requests may come less often when the device is in ambient mode or is not
worn.
You can alternatively use a "push style" to send updates, rather than requesting updates on a
fixed schedule. Use
ProviderUpdateRequester
to trigger calls to onComplicationUpdate
as required. For example:
<meta-data android:name="android.support.wearable.complications.SUPPORTED_TYPES" android:value="RANGED_VALUE,SHORT_TEXT,LONG_TEXT"/> <meta-data android:name="android.support.wearable.complications.UPDATE_PERIOD_SECONDS" android:value="0"/>
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:
<meta-data android:name="android.support.wearable.complications.PROVIDER_CONFIG_ACTION" android:value="PROVIDER_CONFIG_ACTION"/>
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 will attempt to use the provider as a default (see below), 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:
<meta-data android:name="android.support.wearable.complications.SAFE_WATCH_FACES" android:value=" com.app.watchface/com.app.watchface.MyWatchFaceService, com.anotherapp.anotherwatchface/com.something.WatchFaceService, com.something.text"/>
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
.
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.
Do not 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.