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 <noreply@anthropic.com>
This commit is contained in:
Kohei 2026-02-21 20:26:09 +09:00
parent 18309c3f9d
commit 7b13171689
8 changed files with 23 additions and 13 deletions

View file

@ -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"
}

View file

@ -7,6 +7,7 @@
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<queries>
@ -66,7 +67,7 @@
<service
android:name=".assistant.AssistantService"
android:exported="false"
android:foregroundServiceType="specialUse">
android:foregroundServiceType="microphone|specialUse">
<property
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="AI voice assistant overlay for real-time conversation" />

View file

@ -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()

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

@ -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"