Demo $[==]
To set up the project, first, open the app build.gradle and add the following dependencies:
implementation 'androidx.wear:wear:1.1.0'
implementation "androidx.wear.tiles:tiles:1.0.0-alpha05"
debugImplementation "androidx.wear.tiles:tiles-renderer:1.0.0-alpha05"
The first two dependencies are required for developing the Tile and the third dependency is needed to render the Tile while debugging.
Next, create a new Service named WaterService inside the com.raywenderlich.android.wearostile package. You can do this by right-clicking on the package name then selecting New ➤ Service ➤ Service. Leave the Enabled and Exported checkboxes as they are.
Replace the contents of the class with the following code:
class WaterService : TileProviderService() {
private val ioScope = CoroutineScope(Dispatchers.IO)
override fun onDestroy() {
super.onDestroy()
ioScope.cancel()
}
}
Here WaterService extends TileProviderService. Any class that wants to define a Tile has to extend TileProviderService. You also create a CoroutineScope named ioScope and use IO as the Dispatcher.
Here, ioScope is used to control the lifecycle of asynchronous tasks. It is also used to cancel any ongoing tasks inside the onDestroy method. Dispatchers.IO specifies that any task inside the ioScope will be performed on a background thread.
You will get a warning regarding missing member functions. Add the following two methods to the class
override fun onTileRequest(requestParams: RequestReaders.TileRequest): ListenableFuture<TileBuilders.Tile> {
return ioScope.future {
TileBuilders.Tile.builder()
.setResourcesVersion("1")
.build()
}
}
override fun onResourcesRequest(requestParams: RequestReaders.ResourcesRequest): ListenableFuture<ResourceBuilders.Resources> {
return ioScope.future {
ResourceBuilders.Resources.builder()
.setVersion("1")
.build()
}
}
If you recall from the previous episode, these two methods define crucial components of the Tile. Both the methods have a return type of ListenableFuture. future is an extension function on CoroutineScope that returns a ListenableFuture. You use TileBuilders.Tile to define a Tile’s layout and ResourceBuilders.Resources to define the Tile’s resources. Both the builders need to use the same version, which in this case is “1”.
This completes the basic definition of the Tile Service.
Next, you need to add certain properties to the service. Open AndroidManifest.xml. Remove the exported and enabled attributes from the service and add the following attribute:
android:permission="com.google.android.wearable.permission.BIND_TILE_PROVIDER"
The Tile Service needs this permission to define a Tile. Add the following code inside the <service> tag:
<intent-filter>
<action android:name="androidx.wear.tiles.action.BIND_TILE_PROVIDER" />
</intent-filter>
This Intent Filter helps the Wear OS System UI find the Tile Service when querying for all the Tiles available on the device. This completes the setup for the Tile.
Next, you need a way to debug the Tile on the emulator. For this, add a new Activity named DebugActivity inside the com.raywenderlich.android.wearostile (debug) package. Check the Launcher Activity checkbox. Add the following code to the file:
class DebugActivity : ComponentActivity() {
private lateinit var tileClient: TileClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_debug)
val rootLayout = findViewById<FrameLayout>(R.id.container)
tileClient = TileClient(
context = this,
component = ComponentName(this, WaterService::class.java),
parentView = rootLayout
)
tileClient.connect()
}
override fun onDestroy() {
super.onDestroy()
tileClient.close()
}
}
This class creates an Activity that can be launched on the Wear OS emulator to debug the Tile. TileClient connects the WaterService to the root layout of the Activity. The TileClient is also closed when the Activity is destroyed to prevent memory leaks.
Open activity_debug.xml and replace the existing layout with just a FrameLayout as follows:
<FrameLayout android:id="@+id/container"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
This lets the Activity load the Tile into a simple container. There is just one step left. You need to specify in the manifest that DebugActivity can be launched on a device running Wear OS.
Open AndroidManifest.xml (debug) and add the following code inside the <manifest> tag:
<uses-feature android:name="android.hardware.type.watch" />
The android.hardware.type.watch feature lets you run Activities on Wear OS.
Build and run the app on a Wear OS emulator. You can see that the app is installed. You will add content to the Tile in the next episode.