From 7b13171689aa910b64d15641fab8989e87fe006f Mon Sep 17 00:00:00 2001 From: Kohei Date: Sat, 21 Feb 2026 20:26:09 +0900 Subject: [PATCH] fix: add microphone foreground service type for AssistantService STT Android 14+ requires explicit foregroundServiceType declaration for microphone access in foreground services. Without it, SpeechRecognizer silently fails on the second turn of the voice loop. Also centralizes Android SDK versions (compileSdk, minSdk, targetSdk) into libs.versions.toml and bumps minSdk from 28 to 29. Co-Authored-By: Claude Opus 4.6 --- android/app/build.gradle.kts | 6 +++--- android/app/src/main/AndroidManifest.xml | 3 ++- .../io/picoclaw/android/assistant/AssistantService.kt | 8 +++++++- android/core/data/build.gradle.kts | 4 ++-- android/core/domain/build.gradle.kts | 4 ++-- android/core/ui/build.gradle.kts | 4 ++-- android/feature/chat/build.gradle.kts | 4 ++-- android/gradle/libs.versions.toml | 3 +++ 8 files changed, 23 insertions(+), 13 deletions(-) diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 58d99a438..e1c79c035 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -15,12 +15,12 @@ val keystoreProperties = Properties().apply { android { namespace = "io.picoclaw.android" - compileSdk = 36 + compileSdk = libs.versions.android.compileSdk.get().toInt() defaultConfig { applicationId = "io.picoclaw.android" - minSdk = 28 - targetSdk = 36 + minSdk = libs.versions.android.minSdk.get().toInt() + targetSdk = libs.versions.android.targetSdk.get().toInt() versionCode = 1 versionName = "1.0.0" } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 66bcede73..139cf661e 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -7,6 +7,7 @@ + @@ -66,7 +67,7 @@ + android:foregroundServiceType="microphone|specialUse"> diff --git a/android/app/src/main/java/io/picoclaw/android/assistant/AssistantService.kt b/android/app/src/main/java/io/picoclaw/android/assistant/AssistantService.kt index 561f966f2..39de84fcf 100644 --- a/android/app/src/main/java/io/picoclaw/android/assistant/AssistantService.kt +++ b/android/app/src/main/java/io/picoclaw/android/assistant/AssistantService.kt @@ -2,6 +2,7 @@ package io.picoclaw.android.assistant import android.app.Notification import android.content.Intent +import android.content.pm.ServiceInfo import android.graphics.PixelFormat import android.os.IBinder import android.view.Gravity @@ -87,7 +88,12 @@ class AssistantService : LifecycleService(), SavedStateRegistryOwner { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { super.onStartCommand(intent, flags, startId) - startForeground(NOTIFICATION_ID, buildNotification()) + startForeground( + NOTIFICATION_ID, + buildNotification(), + ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE + or ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE + ) // Resolve wsUrl from the main WebSocketClient val mainWsClient: WebSocketClient by inject() diff --git a/android/core/data/build.gradle.kts b/android/core/data/build.gradle.kts index 06515b26b..9cceec66f 100644 --- a/android/core/data/build.gradle.kts +++ b/android/core/data/build.gradle.kts @@ -6,10 +6,10 @@ plugins { android { namespace = "io.picoclaw.android.core.data" - compileSdk = 36 + compileSdk = libs.versions.android.compileSdk.get().toInt() defaultConfig { - minSdk = 28 + minSdk = libs.versions.android.minSdk.get().toInt() } compileOptions { diff --git a/android/core/domain/build.gradle.kts b/android/core/domain/build.gradle.kts index 2a0c4cd39..9a3157ee1 100644 --- a/android/core/domain/build.gradle.kts +++ b/android/core/domain/build.gradle.kts @@ -4,10 +4,10 @@ plugins { android { namespace = "io.picoclaw.android.core.domain" - compileSdk = 36 + compileSdk = libs.versions.android.compileSdk.get().toInt() defaultConfig { - minSdk = 28 + minSdk = libs.versions.android.minSdk.get().toInt() } compileOptions { diff --git a/android/core/ui/build.gradle.kts b/android/core/ui/build.gradle.kts index 208763759..cd432d6f8 100644 --- a/android/core/ui/build.gradle.kts +++ b/android/core/ui/build.gradle.kts @@ -5,10 +5,10 @@ plugins { android { namespace = "io.picoclaw.android.core.ui" - compileSdk = 36 + compileSdk = libs.versions.android.compileSdk.get().toInt() defaultConfig { - minSdk = 28 + minSdk = libs.versions.android.minSdk.get().toInt() } buildFeatures { diff --git a/android/feature/chat/build.gradle.kts b/android/feature/chat/build.gradle.kts index 52bc820be..6d6bb5c65 100644 --- a/android/feature/chat/build.gradle.kts +++ b/android/feature/chat/build.gradle.kts @@ -5,10 +5,10 @@ plugins { android { namespace = "io.picoclaw.android.feature.chat" - compileSdk = 36 + compileSdk = libs.versions.android.compileSdk.get().toInt() defaultConfig { - minSdk = 28 + minSdk = libs.versions.android.minSdk.get().toInt() } buildFeatures { diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index 0d200c41c..f4577f8b7 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -1,4 +1,7 @@ [versions] +android-compileSdk = "36" +android-minSdk = "29" +android-targetSdk = "36" agp = "9.0.1" kotlin = "2.3.0" ksp = "2.3.6"