diff --git a/datalayer/watch/src/main/java/com/google/android/horologist/datalayer/watch/WearDataLayerAppHelper.kt b/datalayer/watch/src/main/java/com/google/android/horologist/datalayer/watch/WearDataLayerAppHelper.kt
index 5516bf7580..a7200a05c0 100644
--- a/datalayer/watch/src/main/java/com/google/android/horologist/datalayer/watch/WearDataLayerAppHelper.kt
+++ b/datalayer/watch/src/main/java/com/google/android/horologist/datalayer/watch/WearDataLayerAppHelper.kt
@@ -189,7 +189,8 @@ public class WearDataLayerAppHelper(
/**
* Marks that the necessary setup steps have been completed in the app such that it is ready for
- * use. Typically this should be called when any pairing/login has been completed.
+ * use. Typically this should be called when any pairing/login has been completed. If used for
+ * prompting login, it should also be called during startup if login happened before
*/
public suspend fun markSetupComplete() {
surfacesInfoDataStore.updateData { info ->
diff --git a/docs/datalayer-helpers-guide.md b/docs/datalayer-helpers-guide.md
index 4ff17bd9a8..26b55c9459 100644
--- a/docs/datalayer-helpers-guide.md
+++ b/docs/datalayer-helpers-guide.md
@@ -1,6 +1,7 @@
# DataLayer helpers libraries
-These libraries provides an easy means to detect and install your app across both watch and phone.
+The DataLayer helpers libraries help tracking the connection between phone and watch and
+start flows from the such as installing the app
However, they are not intended to cover complex use cases, or complex interactions between watch and
phone.
@@ -25,57 +26,64 @@ phone.
For your watch and phone projects respectively.
-1. Add the capability
+2. Add the capabilities
Add a `wear.xml` file in the `res/values` folder with the following content:
- ```xml
+ ```
+
- data_layer_app_helper_device_watch
+
+ - horologist_watch
```
-
+
and
```xml
-
+
+
- data_layer_app_helper_device_phone
-
+
+ - horologist_phone
+
```
- On your watch and phone projects respectively.
+ on your wear and phone projects respectively.
For more details, see
[Specify capability names for detecting your apps](https://developer.android.com/training/wearables/apps/standalone-apps#capability-names).
-1. Initialize the client, including passing a `WearDataLayerRegistry`.
+3. Initialize the client including passing a `WearDataLayerRegistry`.
```kotlin
+ // on your watch project
val appHelper = WearDataLayerAppHelper(context, wearDataLayerRegistry, scope)
- // or
+ // on your phone project
val appHelper = PhoneDataLayerAppHelper(context, wearDataLayerRegistry)
```
+
-## Typical use cases:
-
-1. **Connection and installation status**
+## Connection and installation status
- This is something that your app may do from time to time, or on start up.
+The `DataLayerAppHelper.connectedNodes()` returns information about connected devices. You could
+invoke this method at startup or while the app is running.
- ```kotlin
+```kotlin
val connectedNodes = appHelper.connectedNodes()
- ```
+```
- The resulting list might will contain entries such as:
+The resulting list might will contain entries such as:
- ```
+```
AppHelperNodeStatus(
id=7cd1c38a,
displayName=Google Pixel Watch,
@@ -106,131 +114,131 @@ phone.
usage_status_value: 1
}
)
- ```
+```
-1. **Responding to availability change**
+## Responding to availability change
- Once you've established the app on both devices, you may wish to respond to when the partner
- device connects or disconnects. For example, you may only want to show a "launch workout" button
- on the phone when the watch is connected.
+Once you've established the app on both devices, you may wish to respond to when the partner
+device connects or disconnects. For example, you may only want to show a "launch workout" button
+on the phone when the watch is connected.
- ```kotlin
- val nodes by appHelper.connectedAndInstalledNodes
- .collectAsStateWithLifecycle()
- ```
+```kotlin
+val nodes by appHelper.connectedAndInstalledNodes
+ .collectAsStateWithLifecycle()
+```
-1. **Installing the app on the other device**
+## Installing the app on the other device
- Where the app isn't installed on the other device - be that phone or watch - then the library offers
- a one step option to launch installation:
+Where the app isn't installed on the other device - be that phone or watch - then the library offers
+a one step option to launch installation:
- ```kotlin
- appHelper.installOnNode(node.id)
- ```
+```kotlin
+appHelper.installOnNode(node.id)
+```
-1. **Launching the app on the other device**
+## Launching the app on the other device
- If the app is installed on the other device, you can launch it remotely:
+If the app is installed on the other device, you can launch it remotely:
- ```kotlin
- val result = appHelper.startRemoteOwnApp(node.id)
- ```
+```kotlin
+val result = appHelper.startRemoteOwnApp(node.id)
+```
-1. **Launching a specific activity on the other device**
+## Launching a specific activity on the other device
- In addition to launching your own app, you may wish to launch a different
- activity as part of the user journey:
+In addition to launching your own app, you may wish to launch a different
+activity as part of the user journey:
- ```kotlin
- val config = activityConfig {
- classFullName = "com.example.myapp.MyActivity"
- }
- appHelper.startRemoteActivity(node.id, config)
- ```
+```kotlin
+val config = activityConfig {
+ classFullName = "com.example.myapp.MyActivity"
+}
+appHelper.startRemoteActivity(node.id, config)
+```
-1. **Launching the companion app**
+## Launching the companion app
- In some cases, it can be useful to launch the companion app, either from the watch or the phone.
+In some cases, it can be useful to launch the companion app, either from the watch or the phone.
- For example, if the connected device does not have your Tile installed, you may wish to offer the
- user the option to navigate to the companion app to install it:
+For example, if the connected device does not have your Tile installed, you may wish to offer the
+user the option to navigate to the companion app to install it:
- ```kotlin
- if (node.surfacesInfo.tilesList.isEmpty() && askUserAttempts < MAX_ATTEMPTS) {
- // Show guidance to the user and then launch companion
- // to allow the to install the Tile.
- val result = appHelper.startCompanion(node.id)
- }
- ```
+```kotlin
+if (node.surfacesInfo.tilesList.isEmpty() && askUserAttempts < MAX_ATTEMPTS) {
+ // Show guidance to the user and then launch companion
+ // to allow the to install the Tile.
+ val result = appHelper.startCompanion(node.id)
+}
+```
-1. **Tracking Tile installation** (Wear-only)
+## Tracking Tile installation (Wear-only)
- To determine whether your Tile(s) are installed, add the following to your `TileService`:
+To determine whether your Tile(s) are installed, add the following to your `TileService`:
- In `onTileAddEvent`:
+In `onTileAddEvent`:
- ```kotlin
- wearAppHelper.markTileAsInstalled("SummaryTile")
- ```
+```kotlin
+wearAppHelper.markTileAsInstalled("SummaryTile")
+```
- In `onTileRemoveEvent`:
+In `onTileRemoveEvent`:
- ```kotlin
- wearAppHelper.markTileAsRemoved("SummaryTile")
- ```
+```kotlin
+wearAppHelper.markTileAsRemoved("SummaryTile")
+```
-1. **Tracking Complication installation** (Wear-only)
+## Tracking Complication installation (Wear-only)
- To determine whether your Complication(s) are in-use, add the following to your `ComplicationDataSourceService`:
+To determine whether your Complication(s) are in-use, add the following to your `ComplicationDataSourceService`:
- In `onComplicationActivated`:
+In `onComplicationActivated`:
- ```kotlin
- wearAppHelper.markComplicationAsActivated("GoalsComplication")
- ```
+```kotlin
+wearAppHelper.markComplicationAsActivated("GoalsComplication")
+```
- In `onComplicationDeactivated`:
+In `onComplicationDeactivated`:
- ```kotlin
- wearAppHelper.markComplicationAsDeactivated("GoalsComplication")
- ```
+```kotlin
+wearAppHelper.markComplicationAsDeactivated("GoalsComplication")
+```
-1. **Tracking the main activity has been launched at least once** (Wear-only)
+## Tracking the main activity has been launched at least once (Wear-only)
To mark that your main activity on the watch app has been launched once, use:
- ```kotlin
- wearAppHelper.markActivityLaunchedOnce()
- ```
+```kotlin
+wearAppHelper.markActivityLaunchedOnce()
+```
- To check it on the phone side, use:
+To check it on the phone side, use:
- ```kotlin
- val connectedNodes = appHelper.connectedNodes()
- // after picking a node, check if value is USAGE_STATUS_LAUNCHED_ONCE
- node.surfacesInfo.usageInfo.usageStatus
- ```
+```kotlin
+val connectedNodes = appHelper.connectedNodes()
+// after picking a node, check if value is USAGE_STATUS_LAUNCHED_ONCE
+node.surfacesInfo.usageInfo.usageStatus
+```
-1. **Tracking the app has been set up** (Wear-only)
+## Tracking the app has been set up (Wear-only)
- To mark that the user has completed in the app the necessary setup steps such that it is ready
- for use, use the following:
+To mark that the user has completed in the app the necessary setup steps such that it is ready
+for use, use the following:
- ```kotlin
- wearAppHelper.markSetupComplete()
- ```
+```kotlin
+wearAppHelper.markSetupComplete()
+```
- And when the app is no longer considered in a fully setup state, use the following:
+And when the app is no longer considered in a fully setup state, use the following:
- ```kotlin
- wearAppHelper.markSetupNoLongerComplete()
- ```
+```kotlin
+wearAppHelper.markSetupNoLongerComplete()
+```
- To check it on the phone side, use:
+To check it on the phone side, use:
- ```kotlin
- val connectedNodes = appHelper.connectedNodes()
- // after picking a node, check if value is either USAGE_STATUS_LAUNCHED_ONCE
- // or USAGE_STATUS_SETUP_COMPLETE
- node.surfacesInfo.usageInfo.usageStatus
- ```
+```kotlin
+val connectedNodes = appHelper.connectedNodes()
+// after picking a node, check if value is either USAGE_STATUS_LAUNCHED_ONCE
+// or USAGE_STATUS_SETUP_COMPLETE
+node.surfacesInfo.usageInfo.usageStatus
+```
diff --git a/docs/datalayer-phone-ui.md b/docs/datalayer-phone-ui.md
new file mode 100644
index 0000000000..63cb85c558
--- /dev/null
+++ b/docs/datalayer-phone-ui.md
@@ -0,0 +1,23 @@
+# DataLayer phone UI
+
+The DataLayer phone UI library provides an implementation for phone prompts UI that can be used to
+bring more users to the Wear app.
+
+## Install app
+Use the `InstallAppPrompt` to build the UI of a prompt to ask the user to install the app on their watch.
+
+The `shouldDisplayPrompt` method allows to check if the prompt should be displayed, based on the following conditions:
+
+- there is a watch connected
+
+- the app is not installed
+
+The `shouldDisplayPrompt` method is relying on the capability defined in the wear.xml of the Wear app, if the Wear app is installed
+but hasn't been updated with the capability definition, this method may still return a `AppHelperNodeStatus`
+indicating that the Wear app is not installed.
+
+## ReEngage prompt
+Use the `ReEngagePrompt` to build the UI of a prompt to ask the user to install the app on their watch.
+
+## SignIn prompt
+Use the `SignInPrompt` to build the UI of a prompt to ask the user to finish the sign in on the watch.
diff --git a/docs/datalayer-sample.md b/docs/datalayer-sample.md
new file mode 100644
index 0000000000..ac18ebe2a6
--- /dev/null
+++ b/docs/datalayer-sample.md
@@ -0,0 +1,20 @@
+# DataLayer sample app
+
+The goal of this sample is to show how to use the DataLayer helpers both on phone and watch.
+In order to be able to demo all the features, you need to install the sample both on the watch and
+on the phone
+
+## DataLayer phone sample app
+
+### In-app prompts
+This sample shows how to build in app prompts by using the
+[Phone UI library](https://github.com/google/horologist/tree/main/datalayer/phone-ui) and the
+[PhoneDataLayerAppHelper](https://github.com/google/horologist/blob/main/datalayer/phone/src/main/java/com/google/android/horologist/datalayer/phone/PhoneDataLayerAppHelper.kt).
+
+
+
+
+
+
+
+
diff --git a/docs/datalayer.md b/docs/datalayer.md
index b290b8a066..b7c2288de9 100644
--- a/docs/datalayer.md
+++ b/docs/datalayer.md
@@ -1,13 +1,9 @@
-# DataLayer library
+# Horologist DataLayer library.
-DataStore documentation https://developer.android.com/topic/libraries/architecture/datastore
-
-Direct DataLayer sample code https://github.com/android/wear-os-samples
-
-## DataLayer approach.
-
-The Horologist DataLayer libraries, provide common abstractions on top of the Wearable DataLayer.
-These are built upon a common assumption of Google Protobuf and gRPC, which allows sharing data
+The Horologist DataLayer library, provide common abstractions on top of the
+[Wearable DataLayer](https://developer.android.com/training/wearables/data/data-layer).
+These are built using [Google Protobuf](https://protobuf.dev/) and
+[gRPC](https://grpc.io/docs/what-is-grpc/introduction/), which allows sharing data
definitions throughout your Wear and Mobile apps.
See this
@@ -34,7 +30,8 @@ service CounterService {
## Registering Serializers.
-The WearDataLayerRegistry is an application singleton to register the Serializers.
+The [WearDataLayerRegistry](https://google.github.io/horologist/api/datalayer/core/com.google.android.horologist.data/-wear-data-layer-registry/index.html)
+is an application singleton to register the Serializers.
```kotlin
object CounterValueSerializer : Serializer {
@@ -64,7 +61,8 @@ val registry = WearDataLayerRegistry.fromContext(
## Use Androidx DataStore
This library provides a new implementation of Androidx DataStore, in addition to the local
-Proto and Preferences implementations. The implementation uses the Wearable DataClient
+Proto and Preferences implementations. The implementation uses the
+[WearableDataClient](https://developers.google.com/android/reference/com/google/android/gms/wearable/DataClient)
with a single owner and multiple readers.
See [DataStore](https://developer.android.com/topic/libraries/architecture/datastore).
diff --git a/mkdocs.yml b/mkdocs.yml
index 8cb4f555f3..e5b0aa6267 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -37,6 +37,8 @@ nav:
- 'Data Layer':
- 'Guide': datalayer.md
- 'App Helpers': datalayer-helpers-guide.md
+ - 'Phone UI': datalayer-phone-ui.md
+ - 'Sample': datalayer-sample.md
- 'Media':
- 'Overview': media-toolkit.md
- 'Simple app guide': simple-media-app-guide.md