Skip to content

Commit f900499

Browse files
authored
Merge pull request #168 from garanj/remote-install
Remote install
2 parents 3f310f1 + 0535abd commit f900499

File tree

11 files changed

+103
-15
lines changed

11 files changed

+103
-15
lines changed

core/testing/src/main/java/com/android/developers/testing/repository/FakeWatchFaceInstallationRepository.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ class FakeWatchFaceInstallationRepository : WatchFaceInstallationRepository {
8080
_watchFaceInstallationStatus.value = WatchFaceInstallationStatus.Preparing
8181
}
8282

83+
override suspend fun installAndroidify(nodeId: String) { }
84+
8385
private fun generateTransferId() = UUID.randomUUID().toString().take(8)
8486

8587
public fun setWatchAsConnected() {

feature/results/src/main/java/com/android/developers/androidify/customize/CustomizeExportScreen.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ fun CustomizeAndExportScreen(
130130
onInstallWatchFaceClicked = {
131131
viewModel.installWatchFace()
132132
},
133+
onInstallAndroidifyClicked = {
134+
viewModel.launchPlayInstallOnWatch()
135+
},
133136
onResetWatchFaceSend = {
134137
viewModel.resetWatchFaceSend()
135138
},
@@ -151,6 +154,7 @@ private fun CustomizeExportContents(
151154
onToolSelected: (CustomizeTool) -> Unit,
152155
onSelectedToolStateChanged: (ToolState) -> Unit,
153156
onInstallWatchFaceClicked: () -> Unit,
157+
onInstallAndroidifyClicked: suspend () -> Boolean,
154158
onResetWatchFaceSend: () -> Unit,
155159
layoutType: CustomizeExportLayoutType,
156160
snackbarHostState: SnackbarHostState,
@@ -263,6 +267,9 @@ private fun CustomizeExportContents(
263267
onWatchFaceInstallClick = {
264268
onInstallWatchFaceClicked()
265269
},
270+
onAndroidifyInstallClick = {
271+
onInstallAndroidifyClicked()
272+
},
266273
onLoad = loadWatchFaces,
267274
watchFaceSelectionState = state.watchFaceSelectionState,
268275
onWatchFaceSelect = onWatchFaceSelect,
@@ -599,6 +606,7 @@ fun CustomizeExportPreview() {
599606
layoutType = CustomizeExportLayoutType.Compact,
600607
onSelectedToolStateChanged = {},
601608
onInstallWatchFaceClicked = {},
609+
onInstallAndroidifyClicked = { true },
602610
onResetWatchFaceSend = {},
603611
loadWatchFaces = {},
604612
onWatchFaceSelect = {},
@@ -640,6 +648,7 @@ fun CustomizeExportPreviewLarge() {
640648
layoutType = CustomizeExportLayoutType.Medium,
641649
onSelectedToolStateChanged = {},
642650
onInstallWatchFaceClicked = {},
651+
onInstallAndroidifyClicked = { true },
643652
onResetWatchFaceSend = {},
644653
loadWatchFaces = {},
645654
onWatchFaceSelect = {},

feature/results/src/main/java/com/android/developers/androidify/customize/CustomizeExportViewModel.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import androidx.compose.foundation.layout.fillMaxSize
2222
import androidx.compose.material3.SnackbarHostState
2323
import androidx.compose.ui.Modifier
2424
import androidx.lifecycle.AndroidViewModel
25+
import androidx.lifecycle.application
2526
import androidx.lifecycle.viewModelScope
2627
import com.android.developers.androidify.RemoteConfigDataSource
2728
import com.android.developers.androidify.customize.watchface.WatchFaceSelectionState
@@ -367,6 +368,19 @@ class CustomizeExportViewModel @AssistedInject constructor(
367368
}
368369
}
369370

371+
suspend fun launchPlayInstallOnWatch(): Boolean {
372+
try {
373+
val watch = state.value.connectedWatch
374+
watch?.let {
375+
watchfaceInstallationRepository.installAndroidify(it.nodeId)
376+
}
377+
return true
378+
} catch (e: Exception) {
379+
Timber.e(e, "Failed to open Play Store on watch")
380+
}
381+
return false
382+
}
383+
370384
fun installWatchFace() {
371385
val watchFaceToInstall = _state.value.watchFaceSelectionState.selectedWatchFace ?: return
372386
val bitmap = state.value.exportImageCanvas.imageBitmap

feature/results/src/main/java/com/android/developers/androidify/customize/watchface/InstallAndroidifyPanel.kt

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
*/
1616
package com.android.developers.androidify.customize.watchface
1717

18-
import android.content.Intent
1918
import androidx.compose.foundation.layout.Arrangement
2019
import androidx.compose.foundation.layout.Column
2120
import androidx.compose.foundation.layout.Row
@@ -24,24 +23,33 @@ import androidx.compose.foundation.layout.fillMaxSize
2423
import androidx.compose.foundation.layout.fillMaxWidth
2524
import androidx.compose.foundation.layout.height
2625
import androidx.compose.foundation.layout.padding
26+
import androidx.compose.material3.ButtonDefaults
2727
import androidx.compose.material3.ExperimentalMaterial3Api
28+
import androidx.compose.material3.MaterialTheme
2829
import androidx.compose.runtime.Composable
30+
import androidx.compose.runtime.getValue
31+
import androidx.compose.runtime.mutableStateOf
32+
import androidx.compose.runtime.remember
33+
import androidx.compose.runtime.rememberCoroutineScope
34+
import androidx.compose.runtime.setValue
2935
import androidx.compose.ui.Alignment
3036
import androidx.compose.ui.Modifier
3137
import androidx.compose.ui.platform.LocalContext
3238
import androidx.compose.ui.res.stringResource
3339
import androidx.compose.ui.tooling.preview.Preview
3440
import androidx.compose.ui.unit.dp
35-
import androidx.core.net.toUri
3641
import com.android.developers.androidify.results.R
3742
import com.android.developers.androidify.theme.AndroidifyTheme
3843
import com.android.developers.androidify.watchface.WatchFaceAsset
44+
import kotlinx.coroutines.launch
3945

4046
@Composable
4147
fun InstallAndroidifyPanel(
48+
onInstallClick: suspend () -> Boolean,
4249
modifier: Modifier = Modifier,
4350
) {
4451
val context = LocalContext.current
52+
var isPlayLaunched by remember { mutableStateOf(false) }
4553
val placeholderWatchFace = WatchFaceAsset(
4654
id = "watch_face_1",
4755
previewPath = R.drawable.watch_app_placeholder,
@@ -60,21 +68,47 @@ fun InstallAndroidifyPanel(
6068
) {
6169
WatchFacePreviewItem(
6270
watchFace = placeholderWatchFace,
63-
isSelected = false,
71+
isSelected = true,
6472
onClick = { },
6573
)
6674
}
6775

6876
Spacer(modifier = Modifier.height(24.dp))
77+
78+
val buttonText = if (isPlayLaunched) {
79+
stringResource(R.string.continue_on_watch)
80+
} else {
81+
stringResource(R.string.install_androidify)
82+
}
83+
val launchedColors = ButtonDefaults.buttonColors(
84+
contentColor = MaterialTheme.colorScheme.onSurface,
85+
containerColor = MaterialTheme.colorScheme.secondaryContainer,
86+
)
87+
val installColors = ButtonDefaults.buttonColors(
88+
contentColor = MaterialTheme.colorScheme.surface,
89+
containerColor = MaterialTheme.colorScheme.onSurface,
90+
)
91+
val scope = rememberCoroutineScope()
6992
WatchFacePanelButton(
7093
modifier = modifier.padding(horizontal = 16.dp),
71-
buttonText = stringResource(R.string.install_androidify),
94+
buttonText = buttonText,
7295
iconResId = R.drawable.watch_arrow_24,
7396
onClick = {
74-
val uri = "market://details?id=${context.packageName}".toUri()
75-
val intent = Intent(Intent.ACTION_VIEW, uri)
76-
context.startActivity(intent)
97+
if (!isPlayLaunched) {
98+
scope.launch {
99+
val launchResult = onInstallClick()
100+
if (launchResult) {
101+
isPlayLaunched = true
102+
}
103+
}
104+
}
105+
},
106+
colors = if (isPlayLaunched) {
107+
launchedColors
108+
} else {
109+
installColors
77110
},
111+
isInProgress = isPlayLaunched,
78112
)
79113
}
80114
}
@@ -84,6 +118,6 @@ fun InstallAndroidifyPanel(
84118
@Composable
85119
private fun InstallAndroidifyPanelPreview() {
86120
AndroidifyTheme {
87-
InstallAndroidifyPanel()
121+
InstallAndroidifyPanel({ true })
88122
}
89123
}

feature/results/src/main/java/com/android/developers/androidify/customize/watchface/TransferringWatchFacePanel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ fun TransferringWatchFacePanel(
6464
WatchFacePanelButton(
6565
modifier = Modifier.padding(horizontal = 16.dp),
6666
buttonText = transferLabel,
67-
isSending = true,
67+
isInProgress = true,
6868
colors = ButtonDefaults.buttonColors(
6969
contentColor = MaterialTheme.colorScheme.onSurface,
7070
containerColor = MaterialTheme.colorScheme.secondaryContainer,

feature/results/src/main/java/com/android/developers/androidify/customize/watchface/WatchFaceModalSheet.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ import com.android.developers.androidify.wear.common.WatchFaceInstallationStatus
6464
fun WatchFaceModalSheet(
6565
connectedWatch: ConnectedWatch,
6666
onWatchFaceInstallClick: (String) -> Unit,
67+
onAndroidifyInstallClick: suspend () -> Boolean,
6768
installationStatus: WatchFaceInstallationStatus,
6869
sheetState: SheetState,
6970
watchFaceSelectionState: WatchFaceSelectionState,
@@ -202,7 +203,9 @@ fun WatchFaceModalSheet(
202203
}
203204

204205
else -> {
205-
InstallAndroidifyPanel()
206+
InstallAndroidifyPanel(
207+
onInstallClick = onAndroidifyInstallClick,
208+
)
206209
}
207210
}
208211
}
@@ -243,6 +246,7 @@ private fun WatchFaceModalSheetPreview() {
243246
onLoad = {},
244247
onDismiss = {},
245248
onWatchFaceInstallClick = {},
249+
onAndroidifyInstallClick = { true },
246250
sheetState = sheetState,
247251
)
248252
}

feature/results/src/main/java/com/android/developers/androidify/customize/watchface/WatchFacePanelButton.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ fun WatchFacePanelButton(
4848
modifier: Modifier = Modifier,
4949
onClick: () -> Unit = {},
5050
buttonText: String,
51-
isSending: Boolean = false,
51+
isInProgress: Boolean = false,
5252
iconResId: Int? = null,
5353
colors: ButtonColors = ButtonDefaults.buttonColors(
5454
contentColor = MaterialTheme.colorScheme.surface,
@@ -67,7 +67,7 @@ fun WatchFacePanelButton(
6767
Row(
6868
verticalAlignment = Alignment.CenterVertically,
6969
) {
70-
if (isSending) {
70+
if (isInProgress) {
7171
ContainedLoadingIndicator(
7272
modifier = Modifier.size(24.dp),
7373
containerColor = colors.containerColor,
@@ -92,7 +92,7 @@ private fun WatchFaceInstallButtonPreview() {
9292
WatchFacePanelButton(
9393
onClick = { },
9494
buttonText = stringResource(R.string.send_to_watch),
95-
isSending = false,
95+
isInProgress = false,
9696
iconResId = R.drawable.watch_arrow_24,
9797
)
9898
}
@@ -105,7 +105,7 @@ private fun WatchFaceInstalledButtonPreview() {
105105
WatchFacePanelButton(
106106
onClick = { },
107107
buttonText = stringResource(R.string.watch_face_sent),
108-
isSending = false,
108+
isInProgress = false,
109109
iconResId = R.drawable.check_24,
110110
colors = ButtonDefaults.buttonColors(
111111
contentColor = MaterialTheme.colorScheme.onSurface,
@@ -122,7 +122,7 @@ private fun WatchFaceInstallingButtonPreview() {
122122
WatchFacePanelButton(
123123
onClick = { },
124124
buttonText = stringResource(R.string.sending_to_watch),
125-
isSending = true,
125+
isInProgress = true,
126126
colors = ButtonDefaults.buttonColors(
127127
contentColor = MaterialTheme.colorScheme.onSurface,
128128
containerColor = MaterialTheme.colorScheme.secondaryContainer,

feature/results/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,5 @@
5959
<string name="complete_error_message">Check your watch is connected and try again</string>
6060
<string name="no_watch_faces">"No available watch faces"</string>
6161
<string name="error_dismiss">OK</string>
62+
<string name="continue_on_watch">Continue on watch</string>
6263
</resources>

watchface/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ dependencies {
6161
implementation(libs.validator.push.android) {
6262
exclude(group = "com.google.guava", "listenablefuture")
6363
}
64+
implementation(libs.androidx.wear.remote.interactions)
6465
implementation(libs.bcpkix.jdk18on)
6566
implementation(libs.play.services.wearable)
6667
implementation(libs.kotlinx.coroutines.play.services)

watchface/src/main/java/com/android/developers/androidify/watchface/transfer/EmptyWatchFaceInstallationRepository.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,6 @@ class EmptyWatchFaceInstallationRepositoryImpl @Inject constructor() : WatchFace
4848
override suspend fun resetInstallationStatus() { }
4949

5050
override suspend fun prepareForTransfer() { }
51+
52+
override suspend fun installAndroidify(nodeId: String) { }
5153
}

0 commit comments

Comments
 (0)