diff --git a/datalayer/core/api/current.api b/datalayer/core/api/current.api
index 81a4e298ec..537bf8ec8c 100644
--- a/datalayer/core/api/current.api
+++ b/datalayer/core/api/current.api
@@ -93,31 +93,47 @@ package com.google.android.horologist.data {
package com.google.android.horologist.data.apphelper {
public final class AppHelperNodeStatus {
- ctor public AppHelperNodeStatus(String id, String displayName, boolean isAppInstalled, com.google.android.horologist.data.apphelper.AppHelperNodeType nodeType, optional error.NonExistentClass surfacesInfo);
+ ctor public AppHelperNodeStatus(String id, String displayName, com.google.android.horologist.data.apphelper.AppInstallationStatus appInstallationStatus, optional error.NonExistentClass surfacesInfo);
method public String component1();
method public String component2();
- method public boolean component3();
- method public com.google.android.horologist.data.apphelper.AppHelperNodeType component4();
- method public error.NonExistentClass! component5();
- method public com.google.android.horologist.data.apphelper.AppHelperNodeStatus copy(String id, String displayName, boolean isAppInstalled, com.google.android.horologist.data.apphelper.AppHelperNodeType nodeType, error.NonExistentClass! surfacesInfo);
+ method public com.google.android.horologist.data.apphelper.AppInstallationStatus component3();
+ method public error.NonExistentClass! component4();
+ method public com.google.android.horologist.data.apphelper.AppHelperNodeStatus copy(String id, String displayName, com.google.android.horologist.data.apphelper.AppInstallationStatus appInstallationStatus, error.NonExistentClass! surfacesInfo);
+ method public com.google.android.horologist.data.apphelper.AppInstallationStatus getAppInstallationStatus();
method public String getDisplayName();
method public String getId();
- method public com.google.android.horologist.data.apphelper.AppHelperNodeType getNodeType();
method public error.NonExistentClass! getSurfacesInfo();
- method public boolean isAppInstalled();
+ property public final com.google.android.horologist.data.apphelper.AppInstallationStatus appInstallationStatus;
property public final String displayName;
property public final String id;
- property public final boolean isAppInstalled;
- property public final com.google.android.horologist.data.apphelper.AppHelperNodeType nodeType;
property public final error.NonExistentClass! surfacesInfo;
}
- public enum AppHelperNodeType {
- method public static com.google.android.horologist.data.apphelper.AppHelperNodeType valueOf(String name) throws java.lang.IllegalArgumentException;
- method public static com.google.android.horologist.data.apphelper.AppHelperNodeType[] values();
- enum_constant public static final com.google.android.horologist.data.apphelper.AppHelperNodeType PHONE;
- enum_constant public static final com.google.android.horologist.data.apphelper.AppHelperNodeType UNKNOWN;
- enum_constant public static final com.google.android.horologist.data.apphelper.AppHelperNodeType WATCH;
+ public final class AppHelperNodeStatusKt {
+ method public static boolean getAppInstalled(com.google.android.horologist.data.apphelper.AppHelperNodeStatus);
+ }
+
+ public abstract sealed class AppInstallationStatus {
+ }
+
+ public static final class AppInstallationStatus.Installed extends com.google.android.horologist.data.apphelper.AppInstallationStatus {
+ ctor public AppInstallationStatus.Installed(com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType nodeType);
+ method public com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType component1();
+ method public com.google.android.horologist.data.apphelper.AppInstallationStatus.Installed copy(com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType nodeType);
+ method public com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType getNodeType();
+ property public final com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType nodeType;
+ }
+
+ public static final class AppInstallationStatus.NotInstalled extends com.google.android.horologist.data.apphelper.AppInstallationStatus {
+ field public static final com.google.android.horologist.data.apphelper.AppInstallationStatus.NotInstalled INSTANCE;
+ }
+
+ public enum AppInstallationStatusNodeType {
+ method public static com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType valueOf(String name) throws java.lang.IllegalArgumentException;
+ method public static com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType[] values();
+ enum_constant public static final com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType PHONE;
+ enum_constant public static final com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType UNKNOWN;
+ enum_constant public static final com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType WATCH;
}
public abstract class DataLayerAppHelper {
diff --git a/datalayer/core/src/main/java/com/google/android/horologist/data/apphelper/AppHelperNodeStatus.kt b/datalayer/core/src/main/java/com/google/android/horologist/data/apphelper/AppHelperNodeStatus.kt
index 0dbbc54037..ea419f771f 100644
--- a/datalayer/core/src/main/java/com/google/android/horologist/data/apphelper/AppHelperNodeStatus.kt
+++ b/datalayer/core/src/main/java/com/google/android/horologist/data/apphelper/AppHelperNodeStatus.kt
@@ -25,13 +25,28 @@ import com.google.android.horologist.data.SurfacesInfo
public data class AppHelperNodeStatus(
val id: String,
val displayName: String,
- val isAppInstalled: Boolean,
- val nodeType: AppHelperNodeType,
+ val appInstallationStatus: AppInstallationStatus,
val surfacesInfo: SurfacesInfo = SurfacesInfo.getDefaultInstance(),
)
-public enum class AppHelperNodeType {
- UNKNOWN,
+public sealed class AppInstallationStatus {
+ data object NotInstalled : AppInstallationStatus()
+
+ data class Installed(
+ val nodeType: AppInstallationStatusNodeType,
+ ) : AppInstallationStatus()
+}
+
+public enum class AppInstallationStatusNodeType {
WATCH,
PHONE,
+
+ /**
+ * This case should not happen, but it's here in order to keep the node listed even in a
+ * scenario where there were issues retrieving the capability of the node.
+ */
+ UNKNOWN,
}
+
+public val AppHelperNodeStatus.appInstalled: Boolean
+ get() = this.appInstallationStatus is AppInstallationStatus.Installed
diff --git a/datalayer/core/src/main/java/com/google/android/horologist/data/apphelper/DataLayerAppHelper.kt b/datalayer/core/src/main/java/com/google/android/horologist/data/apphelper/DataLayerAppHelper.kt
index 119639682f..bedde32afd 100644
--- a/datalayer/core/src/main/java/com/google/android/horologist/data/apphelper/DataLayerAppHelper.kt
+++ b/datalayer/core/src/main/java/com/google/android/horologist/data/apphelper/DataLayerAppHelper.kt
@@ -76,16 +76,22 @@ abstract class DataLayerAppHelper(
val allInstalledNodes = installedPhoneNodes + installedWatchNodes
return nearbyNodes.map {
+ val appInstallationStatus = if (allInstalledNodes.contains(it.id)) {
+ val nodeType = when (it.id) {
+ in installedPhoneNodes -> AppInstallationStatusNodeType.PHONE
+ in installedWatchNodes -> AppInstallationStatusNodeType.WATCH
+ else -> AppInstallationStatusNodeType.UNKNOWN
+ }
+ AppInstallationStatus.Installed(nodeType = nodeType)
+ } else {
+ AppInstallationStatus.NotInstalled
+ }
+
AppHelperNodeStatus(
id = it.id,
displayName = it.displayName,
- isAppInstalled = allInstalledNodes.contains(it.id),
+ appInstallationStatus = appInstallationStatus,
surfacesInfo = getSurfaceStatus(it.id),
- nodeType = when (it.id) {
- in installedPhoneNodes -> AppHelperNodeType.PHONE
- in installedWatchNodes -> AppHelperNodeType.WATCH
- else -> AppHelperNodeType.UNKNOWN
- },
)
}
}
diff --git a/datalayer/sample/phone/src/main/java/com/google/android/horologist/datalayer/sample/AppHelperNodeStatusCard.kt b/datalayer/sample/phone/src/main/java/com/google/android/horologist/datalayer/sample/AppHelperNodeStatusCard.kt
index 7608333a13..4181f6aef8 100644
--- a/datalayer/sample/phone/src/main/java/com/google/android/horologist/datalayer/sample/AppHelperNodeStatusCard.kt
+++ b/datalayer/sample/phone/src/main/java/com/google/android/horologist/datalayer/sample/AppHelperNodeStatusCard.kt
@@ -35,7 +35,9 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.google.android.horologist.data.UsageStatus
import com.google.android.horologist.data.apphelper.AppHelperNodeStatus
-import com.google.android.horologist.data.apphelper.AppHelperNodeType
+import com.google.android.horologist.data.apphelper.AppInstallationStatus
+import com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType
+import com.google.android.horologist.data.apphelper.appInstalled
import com.google.android.horologist.data.complicationInfo
import com.google.android.horologist.data.surfacesInfo
import com.google.android.horologist.data.tileInfo
@@ -68,17 +70,22 @@ fun AppHelperNodeStatusCard(
style = MaterialTheme.typography.labelMedium,
text = stringResource(R.string.app_helper_node_id_label, nodeStatus.id),
)
- Text(
- style = MaterialTheme.typography.labelMedium,
- text = stringResource(R.string.app_helper_node_type_label, nodeStatus.nodeType),
- )
Text(
style = MaterialTheme.typography.labelMedium,
text = stringResource(
R.string.app_helper_is_app_installed_label,
- nodeStatus.isAppInstalled,
+ nodeStatus.appInstalled,
),
)
+ val nodeType = if (nodeStatus.appInstalled) {
+ (nodeStatus.appInstallationStatus as AppInstallationStatus.Installed).nodeType
+ } else {
+ stringResource(id = R.string.app_helper_node_type_unknown_label)
+ }
+ Text(
+ style = MaterialTheme.typography.labelMedium,
+ text = stringResource(R.string.app_helper_node_type_label, nodeType),
+ )
if (nodeStatus.surfacesInfo.complicationsList.isNotEmpty()) {
Text(
style = MaterialTheme.typography.labelMedium,
@@ -140,8 +147,9 @@ fun NodeCardPreview() {
val nodeStatus = AppHelperNodeStatus(
displayName = "Pixel Watch",
id = "a1b2c3",
- isAppInstalled = true,
- nodeType = AppHelperNodeType.WATCH,
+ appInstallationStatus = AppInstallationStatus.Installed(
+ nodeType = AppInstallationStatusNodeType.WATCH,
+ ),
surfacesInfo = surfacesInfo {
tiles.add(
tileInfo {
diff --git a/datalayer/sample/phone/src/main/java/com/google/android/horologist/datalayer/sample/MainActivity.kt b/datalayer/sample/phone/src/main/java/com/google/android/horologist/datalayer/sample/MainActivity.kt
index 31de83258b..f3dd8950b6 100644
--- a/datalayer/sample/phone/src/main/java/com/google/android/horologist/datalayer/sample/MainActivity.kt
+++ b/datalayer/sample/phone/src/main/java/com/google/android/horologist/datalayer/sample/MainActivity.kt
@@ -51,7 +51,8 @@ import com.google.android.horologist.data.ProtoDataStoreHelper.protoDataStore
import com.google.android.horologist.data.WearDataLayerRegistry
import com.google.android.horologist.data.WearableApiAvailability
import com.google.android.horologist.data.apphelper.AppHelperNodeStatus
-import com.google.android.horologist.data.apphelper.AppHelperNodeType
+import com.google.android.horologist.data.apphelper.AppInstallationStatus
+import com.google.android.horologist.data.apphelper.AppInstallationStatusNodeType
import com.google.android.horologist.data.complicationInfo
import com.google.android.horologist.data.surfacesInfo
import com.google.android.horologist.data.tileInfo
@@ -96,7 +97,8 @@ class MainActivity : ComponentActivity() {
LaunchedEffect(Unit) {
coroutineScope.launch {
apiAvailable = WearableApiAvailability.isAvailable(registry.dataClient)
- nodeList = if (apiAvailable) phoneDataLayerAppHelper.connectedNodes() else listOf()
+ nodeList =
+ if (apiAvailable) phoneDataLayerAppHelper.connectedNodes() else listOf()
}
}
@@ -202,8 +204,9 @@ fun MainPreview() {
AppHelperNodeStatus(
id = "a1b2c3d4",
displayName = "Pixel Watch",
- isAppInstalled = true,
- nodeType = AppHelperNodeType.WATCH,
+ appInstallationStatus = AppInstallationStatus.Installed(
+ nodeType = AppInstallationStatusNodeType.WATCH,
+ ),
surfacesInfo = surfacesInfo {
tiles.add(
tileInfo {
diff --git a/datalayer/sample/phone/src/main/res/values/strings.xml b/datalayer/sample/phone/src/main/res/values/strings.xml
index ef9e8a2f14..3c44acc461 100644
--- a/datalayer/sample/phone/src/main/res/values/strings.xml
+++ b/datalayer/sample/phone/src/main/res/values/strings.xml
@@ -19,8 +19,9 @@
This device does not have capability to communicate to Wearable Data Layer API
Node: %1$s
ID: %1$s
- Type: %1$s
App installed: %1$s
+ Type: %1$s
+ UNKNOWN (app not installed)
Complications: %1$s
Tiles: %1$s
Usage: %1$s
diff --git a/docs/datalayer-helpers-guide.md b/docs/datalayer-helpers-guide.md
index 11be599bce..d7164518c1 100644
--- a/docs/datalayer-helpers-guide.md
+++ b/docs/datalayer-helpers-guide.md
@@ -50,8 +50,7 @@ phone.
AppHelperNodeStatus(
id=7cd1c38a,
displayName=Google Pixel Watch,
- isAppInstalled=true,
- nodeType=WATCH,
+ appInstallationStatus=Installed(nodeType=WATCH),
surfacesInfo=# SurfacesInfo@125fcbff
complications {
instance_id: 1234