diff --git a/WearComplicationDataSourcesTestSuite/Wearable/src/main/AndroidManifest.xml b/WearComplicationDataSourcesTestSuite/Wearable/src/main/AndroidManifest.xml
index 4d8d16e3f..c9e9b5a91 100644
--- a/WearComplicationDataSourcesTestSuite/Wearable/src/main/AndroidManifest.xml
+++ b/WearComplicationDataSourcesTestSuite/Wearable/src/main/AndroidManifest.xml
@@ -164,6 +164,42 @@
android:value="0" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/Complication.kt b/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/Complication.kt
index 7308e7de6..b59e5c371 100644
--- a/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/Complication.kt
+++ b/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/Complication.kt
@@ -25,10 +25,12 @@ enum class Complication(
*/
val key: String,
) {
+ GOAL_PROGRESS("GoalProgress"),
ICON("Icon"),
LARGE_IMAGE("LargeImage"),
LONG_TEXT("LongText"),
RANGED_VALUE("RangedValue"),
SHORT_TEXT("ShortText"),
SMALL_IMAGE("SmallImage"),
+ WEIGHTED_ELEMENTS("WeightedElements"),
}
diff --git a/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/ComplicationToggleReceiver.kt b/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/ComplicationToggleReceiver.kt
index a5c9e7397..1dc9c776f 100644
--- a/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/ComplicationToggleReceiver.kt
+++ b/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/ComplicationToggleReceiver.kt
@@ -19,6 +19,7 @@ import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
+import androidx.core.os.BundleCompat
import androidx.wear.watchface.complications.datasource.ComplicationDataSourceUpdateRequester
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -68,7 +69,6 @@ class ComplicationToggleReceiver : BroadcastReceiver() {
val intent = Intent(context, ComplicationToggleReceiver::class.java).apply {
putExtra(EXTRA_ARGS, args)
}
-
// Pass complicationId as the requestCode to ensure that different complications get
// different intents.
return PendingIntent.getBroadcast(
@@ -83,7 +83,11 @@ class ComplicationToggleReceiver : BroadcastReceiver() {
* Returns the [ComplicationToggleArgs] from the [Intent] sent to the [ComplicationToggleArgs].
*/
private fun Intent.getArgs(): ComplicationToggleArgs = requireNotNull(
- extras?.getParcelable(EXTRA_ARGS),
+ BundleCompat.getParcelable(
+ this.extras!!,
+ EXTRA_ARGS,
+ ComplicationToggleArgs::class.java,
+ ),
)
}
}
diff --git a/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/GoalProgressDataSourceService.kt b/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/GoalProgressDataSourceService.kt
new file mode 100644
index 000000000..d3fe08c11
--- /dev/null
+++ b/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/GoalProgressDataSourceService.kt
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.wearable.wear.wearcomplicationproviderstestsuite
+
+import android.app.PendingIntent
+import android.content.ComponentName
+import android.graphics.drawable.Icon
+import androidx.annotation.RequiresApi
+import androidx.wear.watchface.complications.data.ComplicationData
+import androidx.wear.watchface.complications.data.ComplicationText
+import androidx.wear.watchface.complications.data.ComplicationType
+import androidx.wear.watchface.complications.data.GoalProgressComplicationData
+import androidx.wear.watchface.complications.data.MonochromaticImage
+import androidx.wear.watchface.complications.data.NoDataComplicationData
+import androidx.wear.watchface.complications.data.PlainComplicationText
+import androidx.wear.watchface.complications.datasource.ComplicationRequest
+import androidx.wear.watchface.complications.datasource.SuspendingComplicationDataSourceService
+import kotlin.random.Random
+
+/**
+ * A complication provider that supports only [ComplicationType.GOAL_PROGRESS] and cycles
+ * through the possible configurations on tap. The value is randomised on each update.
+ */
+@RequiresApi(33)
+class GoalProgressDataSourceService : SuspendingComplicationDataSourceService() {
+
+ override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData? {
+ if (request.complicationType != ComplicationType.GOAL_PROGRESS) {
+ return NoDataComplicationData()
+ }
+ val args = ComplicationToggleArgs(
+ providerComponent = ComponentName(this, javaClass),
+ complication = Complication.GOAL_PROGRESS,
+ complicationInstanceId = request.complicationInstanceId,
+ )
+ val complicationTogglePendingIntent =
+ ComplicationToggleReceiver.getComplicationToggleIntent(
+ context = this,
+ args = args,
+ )
+ // Suspending function to retrieve the complication's state
+ val state = args.getState(this)
+ val case = Case.entries[state.mod(Case.entries.size)]
+
+ return getComplicationData(
+ tapAction = complicationTogglePendingIntent,
+ case = case,
+ )
+ }
+
+ override fun getPreviewData(type: ComplicationType): ComplicationData? =
+ getComplicationData(
+ tapAction = null,
+ case = Case.TEXT_WITH_ICON,
+ )
+
+ private fun getComplicationData(
+ tapAction: PendingIntent?,
+ case: Case,
+ ): ComplicationData {
+ val text: ComplicationText?
+ val monochromaticImage: MonochromaticImage?
+ val title: ComplicationText?
+ val caseContentDescription: String
+
+ // Create a ceiling above the target value, as GOAL_PROGRESS complication data can exceed
+ // the target value.
+ val ceiling = case.targetValue + 5000.0
+ val currentValue = Random.nextDouble(0.0, ceiling).toFloat()
+ val percentage = currentValue / case.targetValue
+
+ when (case) {
+ Case.TEXT_ONLY -> {
+ text = PlainComplicationText.Builder(
+ text = getText(R.string.short_text_only),
+ ).build()
+ monochromaticImage = null
+ title = null
+ caseContentDescription = getString(
+ R.string.goal_progress_text_only_content_description,
+ )
+ }
+ Case.TEXT_WITH_ICON -> {
+ text = PlainComplicationText.Builder(
+ text = getText(R.string.short_text_with_icon),
+ ).build()
+ monochromaticImage = MonochromaticImage.Builder(
+ image = Icon.createWithResource(this, R.drawable.ic_battery),
+ )
+ .setAmbientImage(
+ ambientImage = Icon.createWithResource(
+ this,
+ R.drawable.ic_battery_burn_protect,
+ ),
+ )
+ .build()
+ title = null
+ caseContentDescription = getString(
+ R.string.goal_progress_text_with_icon_content_description,
+ )
+ }
+ Case.TEXT_WITH_TITLE -> {
+ text = PlainComplicationText.Builder(
+ text = getText(R.string.short_text_with_title),
+ ).build()
+ monochromaticImage = null
+ title = PlainComplicationText.Builder(
+ text = getText(R.string.short_title),
+ ).build()
+
+ caseContentDescription = getString(
+ R.string.goal_progress_text_with_title_content_description,
+ )
+ }
+ Case.ICON_ONLY -> {
+ text = null
+ monochromaticImage = MonochromaticImage.Builder(
+ image = Icon.createWithResource(this, R.drawable.ic_event_vd_theme_24),
+ ).build()
+ title = null
+ caseContentDescription = getString(
+ R.string.goal_progress_icon_only_content_description,
+ )
+ }
+ }
+
+ // Create a content description that includes the value information
+ val contentDescription = PlainComplicationText.Builder(
+ text = getString(
+ R.string.goal_progress_content_description,
+ caseContentDescription,
+ currentValue,
+ percentage,
+ case.targetValue,
+ ),
+ )
+ .build()
+
+ return GoalProgressComplicationData.Builder(
+ value = currentValue,
+ targetValue = case.targetValue,
+ contentDescription = contentDescription,
+ )
+ .setText(text)
+ .setMonochromaticImage(monochromaticImage)
+ .setTitle(title)
+ .setTapAction(tapAction)
+ .build()
+ }
+
+ private enum class Case(
+ val targetValue: Float,
+ ) {
+ TEXT_ONLY(5000f),
+ TEXT_WITH_ICON(2500f),
+ TEXT_WITH_TITLE(10000f),
+ ICON_ONLY(10000f),
+ }
+}
diff --git a/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/IconDataSourceService.kt b/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/IconDataSourceService.kt
index 4d50933b3..8964b8b04 100644
--- a/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/IconDataSourceService.kt
+++ b/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/IconDataSourceService.kt
@@ -18,33 +18,24 @@ package com.example.android.wearable.wear.wearcomplicationproviderstestsuite
import android.app.PendingIntent
import android.content.ComponentName
import android.graphics.drawable.Icon
-import androidx.datastore.core.DataStore
import androidx.wear.watchface.complications.data.ComplicationData
import androidx.wear.watchface.complications.data.ComplicationType
import androidx.wear.watchface.complications.data.MonochromaticImage
import androidx.wear.watchface.complications.data.MonochromaticImageComplicationData
+import androidx.wear.watchface.complications.data.NoDataComplicationData
import androidx.wear.watchface.complications.data.PlainComplicationText
-import androidx.wear.watchface.complications.datasource.ComplicationDataSourceService
import androidx.wear.watchface.complications.datasource.ComplicationRequest
import androidx.wear.watchface.complications.datasource.SuspendingComplicationDataSourceService
/**
* A complication provider that supports only [ComplicationType.MONOCHROMATIC_IMAGE] and cycles through
* a few different icons on each tap.
- *
- * Note: This subclasses [SuspendingComplicationDataSourceService] instead of [ComplicationDataSourceService] to support
- * coroutines, so data operations (specifically, calls to [DataStore]) can be supported directly in the
- * [onComplicationRequest].
- *
- * If you don't perform any suspending operations to update your complications, you can subclass
- * [ComplicationDataSourceService] and override [onComplicationRequest] directly.
- * (see [NoDataDataSourceService] for an example)
*/
class IconDataSourceService : SuspendingComplicationDataSourceService() {
override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData? {
if (request.complicationType != ComplicationType.MONOCHROMATIC_IMAGE) {
- return null
+ return NoDataComplicationData()
}
val args = ComplicationToggleArgs(
providerComponent = ComponentName(this, javaClass),
@@ -58,7 +49,7 @@ class IconDataSourceService : SuspendingComplicationDataSourceService() {
)
// Suspending function to retrieve the complication's state
val state = args.getState(this@IconDataSourceService)
- val case = Case.values()[state.mod(Case.values().size)]
+ val case = Case.entries[state.mod(Case.entries.size)]
return getComplicationData(
tapAction = complicationTogglePendingIntent,
case = case,
diff --git a/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/LargeImageDataSourceService.kt b/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/LargeImageDataSourceService.kt
index cd2b5d5f4..3e086ad98 100644
--- a/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/LargeImageDataSourceService.kt
+++ b/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/LargeImageDataSourceService.kt
@@ -18,31 +18,22 @@ package com.example.android.wearable.wear.wearcomplicationproviderstestsuite
import android.app.PendingIntent
import android.content.ComponentName
import android.graphics.drawable.Icon
-import androidx.datastore.core.DataStore
import androidx.wear.watchface.complications.data.ComplicationData
import androidx.wear.watchface.complications.data.ComplicationType
+import androidx.wear.watchface.complications.data.NoDataComplicationData
import androidx.wear.watchface.complications.data.PhotoImageComplicationData
import androidx.wear.watchface.complications.data.PlainComplicationText
-import androidx.wear.watchface.complications.datasource.ComplicationDataSourceService
import androidx.wear.watchface.complications.datasource.ComplicationRequest
import androidx.wear.watchface.complications.datasource.SuspendingComplicationDataSourceService
/**
* A complication provider that supports only [ComplicationType.PHOTO_IMAGE] and cycles
* between a couple of images on tap.
- *
- * Note: This subclasses [SuspendingComplicationDataSourceService] instead of [ComplicationDataSourceService] to support
- * coroutines, so data operations (specifically, calls to [DataStore]) can be supported directly in the
- * [onComplicationRequest].
- *
- * If you don't perform any suspending operations to update your complications, you can subclass
- * [ComplicationDataSourceService] and override [onComplicationRequest] directly.
- * (see [NoDataDataSourceService] for an example)
*/
class LargeImageDataSourceService : SuspendingComplicationDataSourceService() {
override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData? {
if (request.complicationType != ComplicationType.PHOTO_IMAGE) {
- return null
+ return NoDataComplicationData()
}
val args = ComplicationToggleArgs(
providerComponent = ComponentName(this, javaClass),
@@ -61,7 +52,7 @@ class LargeImageDataSourceService : SuspendingComplicationDataSourceService() {
)
// Suspending function to retrieve the complication's state
val state = args.getState(this)
- val case = Case.values()[state.mod(Case.values().size)]
+ val case = Case.entries[state.mod(Case.entries.size)]
return getComplicationData(
tapAction = complicationTogglePendingIntent,
case = case,
diff --git a/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/LongTextDataSourceService.kt b/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/LongTextDataSourceService.kt
index 784dbbb83..6063cbf45 100644
--- a/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/LongTextDataSourceService.kt
+++ b/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/LongTextDataSourceService.kt
@@ -18,34 +18,25 @@ package com.example.android.wearable.wear.wearcomplicationproviderstestsuite
import android.app.PendingIntent
import android.content.ComponentName
import android.graphics.drawable.Icon
-import androidx.datastore.core.DataStore
import androidx.wear.watchface.complications.data.ComplicationData
import androidx.wear.watchface.complications.data.ComplicationType
import androidx.wear.watchface.complications.data.LongTextComplicationData
import androidx.wear.watchface.complications.data.MonochromaticImage
+import androidx.wear.watchface.complications.data.NoDataComplicationData
import androidx.wear.watchface.complications.data.PlainComplicationText
import androidx.wear.watchface.complications.data.SmallImage
import androidx.wear.watchface.complications.data.SmallImageType
-import androidx.wear.watchface.complications.datasource.ComplicationDataSourceService
import androidx.wear.watchface.complications.datasource.ComplicationRequest
import androidx.wear.watchface.complications.datasource.SuspendingComplicationDataSourceService
/**
* A complication provider that supports only [ComplicationType.LONG_TEXT] and cycles
* through the possible configurations on tap.
- *
- * Note: This subclasses [SuspendingComplicationDataSourceService] instead of [ComplicationDataSourceService] to support
- * coroutines, so data operations (specifically, calls to [DataStore]) can be supported directly in the
- * [onComplicationRequest].
- *
- * If you don't perform any suspending operations to update your complications, you can subclass
- * [ComplicationDataSourceService] and override [onComplicationRequest] directly.
- * (see [NoDataDataSourceService] for an example)
*/
class LongTextDataSourceService : SuspendingComplicationDataSourceService() {
override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData? {
if (request.complicationType != ComplicationType.LONG_TEXT) {
- return null
+ return NoDataComplicationData()
}
val args = ComplicationToggleArgs(
providerComponent = ComponentName(this, javaClass),
@@ -59,7 +50,7 @@ class LongTextDataSourceService : SuspendingComplicationDataSourceService() {
)
// Suspending function to retrieve the complication's state
val state = args.getState(this)
- val case = Case.values()[state.mod(Case.values().size)]
+ val case = Case.entries[state.mod(Case.entries.size)]
return getComplicationData(
tapAction = complicationTogglePendingIntent,
case = case,
diff --git a/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/RangedValueDataSourceService.kt b/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/RangedValueDataSourceService.kt
index 98af26a7e..1156d4c5b 100644
--- a/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/RangedValueDataSourceService.kt
+++ b/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/RangedValueDataSourceService.kt
@@ -18,14 +18,13 @@ package com.example.android.wearable.wear.wearcomplicationproviderstestsuite
import android.app.PendingIntent
import android.content.ComponentName
import android.graphics.drawable.Icon
-import androidx.datastore.core.DataStore
import androidx.wear.watchface.complications.data.ComplicationData
import androidx.wear.watchface.complications.data.ComplicationText
import androidx.wear.watchface.complications.data.ComplicationType
import androidx.wear.watchface.complications.data.MonochromaticImage
+import androidx.wear.watchface.complications.data.NoDataComplicationData
import androidx.wear.watchface.complications.data.PlainComplicationText
import androidx.wear.watchface.complications.data.RangedValueComplicationData
-import androidx.wear.watchface.complications.datasource.ComplicationDataSourceService
import androidx.wear.watchface.complications.datasource.ComplicationRequest
import androidx.wear.watchface.complications.datasource.SuspendingComplicationDataSourceService
import kotlin.random.Random
@@ -33,20 +32,12 @@ import kotlin.random.Random
/**
* A complication provider that supports only [ComplicationType.RANGED_VALUE] and cycles
* through the possible configurations on tap. The value is randomised on each update.
- *
- * Note: This subclasses [SuspendingComplicationDataSourceService] instead of [ComplicationDataSourceService] to support
- * coroutines, so data operations (specifically, calls to [DataStore]) can be supported directly in the
- * [onComplicationRequest].
- *
- * If you don't perform any suspending operations to update your complications, you can subclass
- * [ComplicationDataSourceService] and override [onComplicationRequest] directly.
- * (see [NoDataDataSourceService] for an example)
*/
class RangedValueDataSourceService : SuspendingComplicationDataSourceService() {
override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData? {
if (request.complicationType != ComplicationType.RANGED_VALUE) {
- return null
+ return NoDataComplicationData()
}
val args = ComplicationToggleArgs(
providerComponent = ComponentName(this, javaClass),
@@ -60,7 +51,7 @@ class RangedValueDataSourceService : SuspendingComplicationDataSourceService() {
)
// Suspending function to retrieve the complication's state
val state = args.getState(this)
- val case = Case.values()[state.mod(Case.values().size)]
+ val case = Case.entries[state.mod(Case.entries.size)]
return getComplicationData(
tapAction = complicationTogglePendingIntent,
diff --git a/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/ShortTextDataSourceService.kt b/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/ShortTextDataSourceService.kt
index 56b40905a..daf8db798 100644
--- a/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/ShortTextDataSourceService.kt
+++ b/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/ShortTextDataSourceService.kt
@@ -18,32 +18,23 @@ package com.example.android.wearable.wear.wearcomplicationproviderstestsuite
import android.app.PendingIntent
import android.content.ComponentName
import android.graphics.drawable.Icon
-import androidx.datastore.core.DataStore
import androidx.wear.watchface.complications.data.ComplicationData
import androidx.wear.watchface.complications.data.ComplicationType
import androidx.wear.watchface.complications.data.MonochromaticImage
+import androidx.wear.watchface.complications.data.NoDataComplicationData
import androidx.wear.watchface.complications.data.PlainComplicationText
import androidx.wear.watchface.complications.data.ShortTextComplicationData
-import androidx.wear.watchface.complications.datasource.ComplicationDataSourceService
import androidx.wear.watchface.complications.datasource.ComplicationRequest
import androidx.wear.watchface.complications.datasource.SuspendingComplicationDataSourceService
/**
* A complication provider that supports only [ComplicationType.SHORT_TEXT] and cycles
* through the possible configurations on tap.
- *
- * Note: This subclasses [SuspendingComplicationDataSourceService] instead of [ComplicationDataSourceService] to support
- * coroutines, so data operations (specifically, calls to [DataStore]) can be supported directly in the
- * [onComplicationRequest].
- *
- * If you don't perform any suspending operations to update your complications, you can subclass
- * [ComplicationDataSourceService] and override [onComplicationRequest] directly.
- * (see [NoDataDataSourceService] for an example)
*/
class ShortTextDataSourceService : SuspendingComplicationDataSourceService() {
override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData? {
if (request.complicationType != ComplicationType.SHORT_TEXT) {
- return null
+ return NoDataComplicationData()
}
val args = ComplicationToggleArgs(
providerComponent = ComponentName(this, javaClass),
@@ -57,7 +48,7 @@ class ShortTextDataSourceService : SuspendingComplicationDataSourceService() {
)
// Suspending function to retrieve the complication's state
val state = args.getState(this)
- val case = Case.values()[state.mod(Case.values().size)]
+ val case = Case.entries[state.mod(Case.entries.size)]
return getComplicationData(
tapAction = complicationTogglePendingIntent,
case = case,
diff --git a/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/SmallImageDataSourceService.kt b/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/SmallImageDataSourceService.kt
index 27eebb52c..243110655 100644
--- a/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/SmallImageDataSourceService.kt
+++ b/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/SmallImageDataSourceService.kt
@@ -18,33 +18,24 @@ package com.example.android.wearable.wear.wearcomplicationproviderstestsuite
import android.app.PendingIntent
import android.content.ComponentName
import android.graphics.drawable.Icon
-import androidx.datastore.core.DataStore
import androidx.wear.watchface.complications.data.ComplicationData
import androidx.wear.watchface.complications.data.ComplicationType
+import androidx.wear.watchface.complications.data.NoDataComplicationData
import androidx.wear.watchface.complications.data.PlainComplicationText
import androidx.wear.watchface.complications.data.SmallImage
import androidx.wear.watchface.complications.data.SmallImageComplicationData
import androidx.wear.watchface.complications.data.SmallImageType
-import androidx.wear.watchface.complications.datasource.ComplicationDataSourceService
import androidx.wear.watchface.complications.datasource.ComplicationRequest
import androidx.wear.watchface.complications.datasource.SuspendingComplicationDataSourceService
/**
* A complication provider that supports only [ComplicationType.SMALL_IMAGE] and cycles
* between the different image styles on tap.
- *
- * Note: This subclasses [SuspendingComplicationDataSourceService] instead of [ComplicationDataSourceService] to support
- * coroutines, so data operations (specifically, calls to [DataStore]) can be supported directly in the
- * [onComplicationRequest].
- *
- * If you don't perform any suspending operations to update your complications, you can subclass
- * [ComplicationDataSourceService] and override [onComplicationRequest] directly.
- * (see [NoDataDataSourceService] for an example)
*/
class SmallImageDataSourceService : SuspendingComplicationDataSourceService() {
override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData? {
if (request.complicationType != ComplicationType.SMALL_IMAGE) {
- return null
+ return NoDataComplicationData()
}
val args = ComplicationToggleArgs(
providerComponent = ComponentName(this, javaClass),
@@ -58,7 +49,7 @@ class SmallImageDataSourceService : SuspendingComplicationDataSourceService() {
)
// Suspending function to retrieve the complication's state
val state = args.getState(this)
- val case = Case.values()[state.mod(Case.values().size)]
+ val case = Case.entries[state.mod(Case.entries.size)]
return getComplicationData(
tapAction = complicationTogglePendingIntent,
case = case,
diff --git a/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/WeightedElementsDataSourceService.kt b/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/WeightedElementsDataSourceService.kt
new file mode 100644
index 000000000..98718074c
--- /dev/null
+++ b/WearComplicationDataSourcesTestSuite/Wearable/src/main/java/com/example/android/wearable/wear/wearcomplicationproviderstestsuite/WeightedElementsDataSourceService.kt
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.example.android.wearable.wear.wearcomplicationproviderstestsuite
+
+import android.app.PendingIntent
+import android.content.ComponentName
+import android.graphics.Color
+import android.graphics.drawable.Icon
+import androidx.annotation.RequiresApi
+import androidx.wear.watchface.complications.data.ComplicationData
+import androidx.wear.watchface.complications.data.ComplicationText
+import androidx.wear.watchface.complications.data.ComplicationType
+import androidx.wear.watchface.complications.data.MonochromaticImage
+import androidx.wear.watchface.complications.data.NoDataComplicationData
+import androidx.wear.watchface.complications.data.PlainComplicationText
+import androidx.wear.watchface.complications.data.WeightedElementsComplicationData
+import androidx.wear.watchface.complications.datasource.ComplicationRequest
+import androidx.wear.watchface.complications.datasource.SuspendingComplicationDataSourceService
+import kotlin.random.Random
+
+/**
+ * A complication provider that supports only [ComplicationType.WEIGHTED_ELEMENTS] and cycles
+ * through the possible configurations on tap. The value is randomised on each update.
+ */
+@RequiresApi(33)
+class WeightedElementsDataSourceService : SuspendingComplicationDataSourceService() {
+
+ override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData? {
+ if (request.complicationType != ComplicationType.WEIGHTED_ELEMENTS) {
+ return NoDataComplicationData()
+ }
+ val args = ComplicationToggleArgs(
+ providerComponent = ComponentName(this, javaClass),
+ complication = Complication.WEIGHTED_ELEMENTS,
+ complicationInstanceId = request.complicationInstanceId,
+ )
+ val complicationTogglePendingIntent =
+ ComplicationToggleReceiver.getComplicationToggleIntent(
+ context = this,
+ args = args,
+ )
+ // Suspending function to retrieve the complication's state
+ val state = args.getState(this)
+ val case = Case.entries[state.mod(Case.entries.size)]
+
+ return getComplicationData(
+ tapAction = complicationTogglePendingIntent,
+ case = case,
+ )
+ }
+
+ override fun getPreviewData(type: ComplicationType): ComplicationData? =
+ getComplicationData(
+ tapAction = null,
+ case = Case.TEXT_WITH_ICON,
+ )
+
+ private fun getComplicationData(
+ tapAction: PendingIntent?,
+ case: Case,
+ ): ComplicationData {
+ val text: ComplicationText?
+ val monochromaticImage: MonochromaticImage?
+ val title: ComplicationText?
+ val caseContentDescription: String
+
+ when (case) {
+ Case.TEXT_ONLY -> {
+ text = PlainComplicationText.Builder(
+ text = getText(R.string.short_text_only),
+ ).build()
+ monochromaticImage = null
+ title = null
+ caseContentDescription = getString(
+ R.string.weighted_elements_text_only_content_description,
+ )
+ }
+ Case.TEXT_WITH_ICON -> {
+ text = PlainComplicationText.Builder(
+ text = getText(R.string.short_text_with_icon),
+ ).build()
+ monochromaticImage = MonochromaticImage.Builder(
+ image = Icon.createWithResource(this, R.drawable.ic_battery),
+ )
+ .setAmbientImage(
+ ambientImage = Icon.createWithResource(
+ this,
+ R.drawable.ic_battery_burn_protect,
+ ),
+ )
+ .build()
+ title = null
+ caseContentDescription = getString(
+ R.string.weighted_elements_text_with_icon_content_description,
+ )
+ }
+ Case.TEXT_WITH_TITLE -> {
+ text = PlainComplicationText.Builder(
+ text = getText(R.string.short_text_with_title),
+ ).build()
+ monochromaticImage = null
+ title = PlainComplicationText.Builder(
+ text = getText(R.string.short_title),
+ ).build()
+
+ caseContentDescription = getString(
+ R.string.weighted_elements_text_with_title_content_description,
+ )
+ }
+ Case.ICON_ONLY -> {
+ text = null
+ monochromaticImage = MonochromaticImage.Builder(
+ image = Icon.createWithResource(this, R.drawable.ic_event_vd_theme_24),
+ ).build()
+ title = null
+ caseContentDescription = getString(
+ R.string.weighted_elements_icon_only_content_description,
+ )
+ }
+ }
+
+ // Create a content description that includes the value information
+ val contentDescription = PlainComplicationText.Builder(
+ text = getString(
+ R.string.weighted_elements_content_description,
+ caseContentDescription,
+ case.numElements,
+ resources.getQuantityString(R.plurals.number_of_elements, case.numElements),
+ ),
+ )
+ .build()
+
+ return WeightedElementsComplicationData.Builder(
+ elements = createWeightedElements(case.numElements),
+ contentDescription = contentDescription,
+ )
+ .setText(text)
+ .setMonochromaticImage(monochromaticImage)
+ .setTitle(title)
+ .setTapAction(tapAction)
+ .build()
+ }
+
+ private fun createWeightedElements(numElements: Int):
+ List {
+ val elements = mutableListOf()
+ repeat(numElements) { index ->
+ val weight = Random.nextInt(1, 3).toFloat()
+ val color = colors[(index % colors.size)]
+ elements.add(WeightedElementsComplicationData.Element(weight, color))
+ }
+ return elements
+ }
+
+ private enum class Case(
+ val numElements: Int,
+ ) {
+ TEXT_ONLY(5),
+ TEXT_WITH_ICON(3),
+ TEXT_WITH_TITLE(4),
+ ICON_ONLY(4),
+ }
+
+ private val colors = listOf(
+ Color.argb(255, 255, 0, 0),
+ Color.argb(255, 0, 255, 0),
+ Color.argb(255, 0, 0, 255),
+ )
+}
diff --git a/WearComplicationDataSourcesTestSuite/Wearable/src/main/res/values/strings.xml b/WearComplicationDataSourcesTestSuite/Wearable/src/main/res/values/strings.xml
index a20080242..45f25e10e 100644
--- a/WearComplicationDataSourcesTestSuite/Wearable/src/main/res/values/strings.xml
+++ b/WearComplicationDataSourcesTestSuite/Wearable/src/main/res/values/strings.xml
@@ -20,10 +20,12 @@
No Data
Short Text
Ranged Value
+ Goal Progress
Long Text
Icon
Small Image
Large Image
+ Weighted Elements
Face
Battery
@@ -40,6 +42,18 @@
Text with title
Icon only
%1$s at %2$.2f, %3$.0f%% between %4$.2f and %5$.2f
+
+ Text only
+ Text with icon
+ Text with title
+ Icon only
+ %1$s at %2$.2f, %3$.0f%%. Target %4$.2f
+
+ Text only
+ Text with icon
+ Text with title
+ Icon only
+ %1$s with %2$d %3$s
TxtOnly
Short Text Only
@@ -64,4 +78,9 @@
Text w/ Image & Title
Text with Image and Title
Long Title
+
+
+ - element
+ - elements
+
\ No newline at end of file
diff --git a/WearComplicationDataSourcesTestSuite/gradle/libs.versions.toml b/WearComplicationDataSourcesTestSuite/gradle/libs.versions.toml
index 61af72491..100113fe5 100644
--- a/WearComplicationDataSourcesTestSuite/gradle/libs.versions.toml
+++ b/WearComplicationDataSourcesTestSuite/gradle/libs.versions.toml
@@ -1,29 +1,17 @@
[versions]
android-gradle-plugin = "8.3.2"
-androidx-activity = "1.4.0"
-androidx-lifecycle = "2.5.1"
-androidx-test = "1.4.0"
-androidx-wear-compose = "1.1.0-rc01"
-androidx-wear-tiles = "1.1.0"
androidx-wear-watchface = "1.2.1"
-compose = "1.5.0-beta01"
-ktlint = "0.50.0"
+
org-jetbrains-kotlin = "1.9.23"
org-jetbrains-kotlinx = "1.8.0"
[libraries]
-android-lint-gradle = "com.android.tools.lint:lint-gradle:31.3.2"
androidx-core-ktx = "androidx.core:core-ktx:1.13.0"
-androidx-databinding-viewbinding = "androidx.databinding:viewbinding:8.3.2"
androidx-datastore-preferences = "androidx.datastore:datastore-preferences:1.1.0"
androidx-wear-watchface-complications-data-source-ktx = { module = "androidx.wear.watchface:watchface-complications-data-source-ktx", version.ref = "androidx-wear-watchface" }
-jacoco-ant = "org.jacoco:org.jacoco.ant:0.8.12"
kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "org-jetbrains-kotlin" }
-kotlin-parcelize-compiler = { module = "org.jetbrains.kotlin:kotlin-parcelize-compiler", version.ref = "org-jetbrains-kotlin" }
-kotlin-parcelize-runtime = { module = "org.jetbrains.kotlin:kotlin-parcelize-runtime", version.ref = "org-jetbrains-kotlin" }
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "org-jetbrains-kotlinx" }
[plugins]
com-android-application = { id = "com.android.application", version.ref = "android-gradle-plugin" }
com-diffplug-spotless = "com.diffplug.spotless:6.25.0"
-org-jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "org-jetbrains-kotlin" }