Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions wear/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,21 @@
<!-- [END android_wear_complication_intent_filter] -->
</activity>

<service
android:name=".snippets.m3.tile.StateTile"
android:label="@string/tile_label"
android:description="@string/tile_description"
android:icon="@mipmap/ic_launcher"
android:exported="true"
android:permission="com.google.android.wearable.permission.BIND_TILE_PROVIDER">
<intent-filter>
<action android:name="androidx.wear.tiles.action.BIND_TILE_PROVIDER" />
</intent-filter>

<meta-data android:name="androidx.wear.tiles.PREVIEW"
android:resource="@drawable/tile_preview" />
</service>

</application>

</manifest>
99 changes: 99 additions & 0 deletions wear/src/main/java/com/example/wear/snippets/m3/tile/Tile.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,29 @@
package com.example.wear.snippets.m3.tile

import android.content.Context
import androidx.wear.protolayout.LayoutElementBuilders
import androidx.wear.protolayout.LayoutElementBuilders.Column
import androidx.wear.protolayout.ResourceBuilders.Resources
import androidx.wear.protolayout.StateBuilders
import androidx.wear.protolayout.TimelineBuilders.Timeline
import androidx.wear.protolayout.expression.DynamicBuilders
import androidx.wear.protolayout.expression.dynamicDataMapOf
import androidx.wear.protolayout.expression.intAppDataKey
import androidx.wear.protolayout.expression.mapTo
import androidx.wear.protolayout.expression.stringAppDataKey
import androidx.wear.protolayout.material3.MaterialScope
import androidx.wear.protolayout.material3.Typography.BODY_LARGE
import androidx.wear.protolayout.material3.Typography.BODY_MEDIUM
import androidx.wear.protolayout.material3.button
import androidx.wear.protolayout.material3.buttonGroup
import androidx.wear.protolayout.material3.materialScope
import androidx.wear.protolayout.material3.primaryLayout
import androidx.wear.protolayout.material3.text
import androidx.wear.protolayout.material3.textButton
import androidx.wear.protolayout.modifiers.clickable
import androidx.wear.protolayout.modifiers.loadAction
import androidx.wear.protolayout.types.asLayoutConstraint
import androidx.wear.protolayout.types.asLayoutString
import androidx.wear.protolayout.types.layoutString
import androidx.wear.tiles.RequestBuilders
import androidx.wear.tiles.RequestBuilders.ResourcesRequest
Expand All @@ -37,6 +50,7 @@ import androidx.wear.tiles.tooling.preview.TilePreviewData
import androidx.wear.tiles.tooling.preview.TilePreviewHelper
import androidx.wear.tooling.preview.devices.WearDevices
import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture

private const val RESOURCES_VERSION = "1"

Expand Down Expand Up @@ -139,3 +153,88 @@ fun smallPreview(context: Context) = TilePreviewData {
.build()
}
// [END android_wear_tile_preview]

class StateTile : TileService() {
// [START android_wear_tile_dynamic_ontilerequest]
override fun onTileRequest(
requestParams: RequestBuilders.TileRequest
): ListenableFuture<Tile?> {
// If the tile hasn't had any state set yet, use the default values
val state =
if (requestParams.currentState.keyToValueMapping.isNotEmpty())
requestParams.currentState
else
StateBuilders.State.Builder()
.setStateMap(
dynamicDataMapOf(
KEY_WATER_INTAKE mapTo 200,
KEY_NOTE mapTo "Good"
)
)
.build()

return Futures.immediateFuture(
Tile.Builder()
// Set resources, timeline, and other tile properties.
// [START_EXCLUDE silent]
.setTileTimeline(
Timeline.fromLayoutElement(
materialScope(this, requestParams.deviceConfiguration) {
tileLayout()
}
)
)
// [END_EXCLUDE]
.setState(state)
.build()
)
}
// [END android_wear_tile_dynamic_ontilerequest]

fun MaterialScope.tileLayout(): LayoutElementBuilders.LayoutElement {
return primaryLayout(
mainSlot = {
// [START android_wear_tile_dynamic_showdata]
val waterIntakeValue =
DynamicBuilders.DynamicInt32.from(KEY_WATER_INTAKE)
// [END android_wear_tile_dynamic_showdata]
.format()
.asLayoutString("0", "000".asLayoutConstraint())
val noteValue =
DynamicBuilders.DynamicString.from(KEY_NOTE)
.asLayoutString(
"",
"Note about day".asLayoutConstraint()
)

// [START android_wear_tile_dynamic_loadaction]
val loadAction =
loadAction(
dynamicDataMapOf(
KEY_WATER_INTAKE mapTo 400,
KEY_NOTE mapTo "Outstanding"
)
)
// [END android_wear_tile_dynamic_loadaction]

Column.Builder()
.addContent(text(waterIntakeValue, typography = BODY_LARGE))
.addContent(text(noteValue, typography = BODY_MEDIUM))
.addContent(
textButton(
onClick = clickable(loadAction),
labelContent = { text("Load".layoutString) }
)
)
.build()
}
)
}

// [START android_wear_tile_dynamic_companion]
companion object {
val KEY_WATER_INTAKE = intAppDataKey("key_water_intake")
val KEY_NOTE = stringAppDataKey("key_note")
}
// [END android_wear_tile_dynamic_companion]
}