feat(audio): Background-Service auch fuer Wake-Word + Aufnahme + Doku-Split
Erweitert den Foreground-Service um den microphone-Type damit nicht nur TTS, sondern auch Wake-Word-Lauschen und aktive Aufnahmen weiterlaufen wenn die App im Hintergrund ist. Slot-System (backgroundAudio.ts): - 'tts' : ARIA spricht - 'rec' : Aufnahme laeuft - 'wake' : Wake-Word lauscht passiv (Ohr aktiv) Mehrere Slots koennen unabhaengig acquired/released werden, der Service laeuft solange mindestens einer aktiv ist. Notification-Text passt sich dynamisch an den hoechstprioren Slot an (tts > rec > wake). Wiring (ChatScreen): - onPlaybackStarted/Finished → 'tts' Slot - audioService.onStateChange (recording) → 'rec' Slot - wakeWordService.onStateChange (off→armed/conversing) → 'wake' Slot AndroidManifest: - foregroundServiceType="mediaPlayback|microphone" (Pflicht ab Android 14 fuer Background-Mic-Zugriff) - FOREGROUND_SERVICE_MICROPHONE Permission Doku: - issue.md Erledigt-Sektion in "Bugs / Fixes", "App Features" und "Infrastruktur" gesplittet - README: Background-Service-Beschreibung erweitert Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -27,17 +27,22 @@ class AriaPlaybackService : Service() {
|
||||
private const val TAG = "AriaPlaybackService"
|
||||
private const val CHANNEL_ID = "aria_playback"
|
||||
private const val NOTIFICATION_ID = 1042
|
||||
const val EXTRA_REASON = "reason" // "tts" | "wake" | "rec" | ""
|
||||
}
|
||||
|
||||
private var currentReason: String = ""
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
ensureNotificationChannel()
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
Log.i(TAG, "Foreground-Service gestartet")
|
||||
val reason = intent?.getStringExtra(EXTRA_REASON) ?: ""
|
||||
currentReason = reason
|
||||
Log.i(TAG, "Foreground-Service start/update (reason=$reason)")
|
||||
try {
|
||||
startForeground(NOTIFICATION_ID, buildNotification())
|
||||
startForeground(NOTIFICATION_ID, buildNotification(reason))
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "startForeground fehlgeschlagen", e)
|
||||
stopSelf()
|
||||
@@ -71,7 +76,7 @@ class AriaPlaybackService : Service() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildNotification(): Notification {
|
||||
private fun buildNotification(reason: String): Notification {
|
||||
val launchIntent = Intent(this, MainActivity::class.java).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
}
|
||||
@@ -81,9 +86,16 @@ class AriaPlaybackService : Service() {
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
val pendingIntent = PendingIntent.getActivity(this, 0, launchIntent, pendingFlags)
|
||||
|
||||
val (title, body) = when (reason) {
|
||||
"tts" -> "ARIA spricht" to "Antwort wird abgespielt — antippen oeffnet die App"
|
||||
"rec" -> "ARIA hoert zu" to "Sprachaufnahme laeuft — antippen oeffnet die App"
|
||||
"wake" -> "ARIA bereit" to "Wake-Word lauscht passiv — antippen oeffnet die App"
|
||||
else -> "ARIA aktiv" to "Hintergrund-Modus — antippen oeffnet die App"
|
||||
}
|
||||
|
||||
return NotificationCompat.Builder(this, CHANNEL_ID)
|
||||
.setContentTitle("ARIA spricht")
|
||||
.setContentText("Antwort wird abgespielt — antippen oeffnet die App")
|
||||
.setContentTitle(title)
|
||||
.setContentText(body)
|
||||
.setSmallIcon(R.mipmap.ic_launcher)
|
||||
.setContentIntent(pendingIntent)
|
||||
.setOngoing(true)
|
||||
|
||||
@@ -25,10 +25,11 @@ class BackgroundAudioModule(reactContext: ReactApplicationContext) : ReactContex
|
||||
companion object { private const val TAG = "BackgroundAudio" }
|
||||
|
||||
@ReactMethod
|
||||
fun start(promise: Promise) {
|
||||
fun start(reason: String, promise: Promise) {
|
||||
try {
|
||||
val ctx = reactApplicationContext
|
||||
val intent = Intent(ctx, AriaPlaybackService::class.java)
|
||||
intent.putExtra(AriaPlaybackService.EXTRA_REASON, reason ?: "")
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
ctx.startForegroundService(intent)
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user