Skip to content

Commit 0912308

Browse files
Address Live sample compose comments
1 parent 65be3cc commit 0912308

File tree

3 files changed

+37
-25
lines changed

3 files changed

+37
-25
lines changed

ai-catalog/samples/gemini-live-todo/src/main/java/com/android/ai/samples/geminilivetodo/ui/TodoScreen.kt

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@
1515
*/
1616
package com.android.ai.samples.geminilivetodo.ui
1717

18+
import android.Manifest
1819
import android.app.Activity
20+
import android.content.pm.PackageManager
21+
import android.widget.Toast
1922
import androidx.activity.compose.LocalActivity
2023
import androidx.compose.animation.Animatable
2124
import androidx.compose.animation.animateColor
@@ -71,6 +74,8 @@ import androidx.compose.ui.text.TextStyle
7174
import androidx.compose.ui.text.style.TextDecoration
7275
import androidx.compose.ui.unit.dp
7376
import androidx.compose.ui.unit.sp
77+
import androidx.core.app.ActivityCompat
78+
import androidx.core.content.ContextCompat
7479
import androidx.hilt.navigation.compose.hiltViewModel
7580
import androidx.lifecycle.compose.collectAsStateWithLifecycle
7681
import com.android.ai.samples.geminilivetodo.R
@@ -90,7 +95,8 @@ fun TodoScreen(viewModel: TodoScreenViewModel = hiltViewModel()) {
9095
val activity = LocalActivity.current as Activity
9196

9297
LaunchedEffect(Unit) {
93-
viewModel.initializeGeminiLive(activity)
98+
requestAudioPermissionIfNeeded(activity)
99+
viewModel.initializeGeminiLive()
94100
}
95101

96102
Scaffold(
@@ -106,7 +112,18 @@ fun TodoScreen(viewModel: TodoScreenViewModel = hiltViewModel()) {
106112
floatingActionButton = {
107113
MicButton(
108114
uiState = uiState,
109-
onToggle = { viewModel.toggleLiveSession(activity) },
115+
modifier = Modifier,
116+
onToggle = {
117+
if (ContextCompat.checkSelfPermission(
118+
activity,
119+
Manifest.permission.RECORD_AUDIO,
120+
) == PackageManager.PERMISSION_GRANTED
121+
) {
122+
viewModel.toggleLiveSession()
123+
} else {
124+
Toast.makeText(activity, R.string.error_permission, Toast.LENGTH_SHORT).show()
125+
}
126+
},
110127
)
111128
},
112129
floatingActionButtonPosition = FabPosition.Center,
@@ -121,6 +138,7 @@ fun TodoScreen(viewModel: TodoScreenViewModel = hiltViewModel()) {
121138
) {
122139
TodoInput(
123140
text = text,
141+
modifier = Modifier,
124142
onTextChange = { text = it },
125143
onAddClick = {
126144
viewModel.addTodo(text)
@@ -176,7 +194,7 @@ fun TodoScreen(viewModel: TodoScreenViewModel = hiltViewModel()) {
176194
}
177195

178196
@Composable
179-
fun TodoInput(text: String, onTextChange: (String) -> Unit, onAddClick: () -> Unit) {
197+
fun TodoInput(text: String, modifier: Modifier, onTextChange: (String) -> Unit, onAddClick: () -> Unit) {
180198
Row(
181199
modifier = Modifier
182200
.fillMaxWidth()
@@ -201,7 +219,7 @@ fun TodoInput(text: String, onTextChange: (String) -> Unit, onAddClick: () -> Un
201219
}
202220

203221
@Composable
204-
fun MicButton(uiState: TodoScreenUiState, onToggle: () -> Unit) {
222+
fun MicButton(uiState: TodoScreenUiState, modifier: Modifier, onToggle: () -> Unit) {
205223
if (uiState is TodoScreenUiState.Success) {
206224
val micIcon = when {
207225
uiState.liveSessionState is LiveSessionState.Ready -> Icons.Filled.MicOff
@@ -283,3 +301,13 @@ fun TodoItem(modifier: Modifier, task: Todo, onToggle: () -> Unit, onDelete: ()
283301
}
284302
}
285303
}
304+
305+
private fun requestAudioPermissionIfNeeded(activity: Activity) {
306+
if (ContextCompat.checkSelfPermission(
307+
activity,
308+
Manifest.permission.RECORD_AUDIO,
309+
) != PackageManager.PERMISSION_GRANTED
310+
) {
311+
ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.RECORD_AUDIO), 1)
312+
}
313+
}

ai-catalog/samples/gemini-live-todo/src/main/java/com/android/ai/samples/geminilivetodo/ui/TodoScreenViewModel.kt

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -83,20 +83,14 @@ class TodoScreenViewModel @Inject constructor(private val todoRepository: TodoRe
8383
}
8484

8585
@SuppressLint("MissingPermission")
86-
fun toggleLiveSession(activity: Activity) {
86+
fun toggleLiveSession() {
8787
viewModelScope.launch {
8888
if (liveSessionState.value is LiveSessionState.NotReady) return@launch
8989

9090
session?.let {
9191
if (liveSessionState.value is LiveSessionState.Ready) {
92-
if (ContextCompat.checkSelfPermission(
93-
activity,
94-
Manifest.permission.RECORD_AUDIO,
95-
) == PackageManager.PERMISSION_GRANTED
96-
) {
97-
it.startAudioConversation(::handleFunctionCall)
98-
liveSessionState.value = LiveSessionState.Running
99-
}
92+
it.startAudioConversation(::handleFunctionCall)
93+
liveSessionState.value = LiveSessionState.Running
10094
} else {
10195
it.stopAudioConversation()
10296
liveSessionState.value = LiveSessionState.Ready
@@ -105,8 +99,7 @@ class TodoScreenViewModel @Inject constructor(private val todoRepository: TodoRe
10599
}
106100
}
107101

108-
fun initializeGeminiLive(activity: Activity) {
109-
requestAudioPermissionIfNeeded(activity)
102+
fun initializeGeminiLive() {
110103
viewModelScope.launch {
111104
Log.d(TAG, "Start Gemini Live initialization")
112105
val liveGenerationConfig = liveGenerationConfig {
@@ -233,14 +226,4 @@ class TodoScreenViewModel @Inject constructor(private val todoRepository: TodoRe
233226
}
234227
}
235228
}
236-
237-
fun requestAudioPermissionIfNeeded(activity: Activity) {
238-
if (ContextCompat.checkSelfPermission(
239-
activity,
240-
Manifest.permission.RECORD_AUDIO,
241-
) != PackageManager.PERMISSION_GRANTED
242-
) {
243-
ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.RECORD_AUDIO), 1)
244-
}
245-
}
246229
}

ai-catalog/samples/gemini-live-todo/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
<string name="add_button">Add</string>
2222
<string name="error_title">Error</string>
2323
<string name="error_message">The live session model could not be initialized.</string>
24+
<string name="error_permission">Enable audio recording permission.</string>
2425
<string name="dismiss_button">Dismiss</string>
2526
<string name="interact_with_todolist_by_voice">Button to start the live session and interact with the todo list by voice</string>
2627
</resources>

0 commit comments

Comments
 (0)