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,7 +27,10 @@ import audioService from '../services/audio';
|
||||
import wakeWordService from '../services/wakeword';
|
||||
import phoneCallService from '../services/phoneCall';
|
||||
import { playWakeReadySound } from '../services/wakeReadySound';
|
||||
import { startBackgroundAudio, stopBackgroundAudio } from '../services/backgroundAudio';
|
||||
import {
|
||||
acquireBackgroundAudio,
|
||||
releaseBackgroundAudio,
|
||||
} from '../services/backgroundAudio';
|
||||
import updateService from '../services/updater';
|
||||
import VoiceButton from '../components/VoiceButton';
|
||||
import FileUpload, { FileData } from '../components/FileUpload';
|
||||
@@ -174,6 +177,11 @@ const ChatScreen: React.FC = () => {
|
||||
// 'armed' oder 'off' fallen, darf Spotify wieder.
|
||||
if (s === 'conversing') audioService.acquireConversationFocus();
|
||||
else audioService.releaseConversationFocus();
|
||||
// Foreground-Service-Slot 'wake' — solange das Ohr ueberhaupt aktiv ist
|
||||
// (armed oder conversing), soll der App-Prozess im Hintergrund am Leben
|
||||
// bleiben damit Mikro-Lauschen + Aufnahme weiterlaufen.
|
||||
if (s !== 'off') acquireBackgroundAudio('wake').catch(() => {});
|
||||
else releaseBackgroundAudio('wake').catch(() => {});
|
||||
});
|
||||
return () => unsub();
|
||||
}, []);
|
||||
@@ -185,6 +193,17 @@ const ChatScreen: React.FC = () => {
|
||||
return () => { phoneCallService.stop().catch(() => {}); };
|
||||
}, []);
|
||||
|
||||
// Recording-State an Background-Service-Slot 'rec' koppeln — damit das Mikro
|
||||
// auch im Hintergrund weiter aufnehmen darf (Android killt den App-Prozess
|
||||
// sonst und die Aufnahme bricht ab).
|
||||
useEffect(() => {
|
||||
const unsub = audioService.onStateChange((s) => {
|
||||
if (s === 'recording') acquireBackgroundAudio('rec').catch(() => {});
|
||||
else releaseBackgroundAudio('rec').catch(() => {});
|
||||
});
|
||||
return () => unsub();
|
||||
}, []);
|
||||
|
||||
// ttsCanPlayRef live aktuell halten — Closure in onMessage unten liest
|
||||
// darueber statt direkt ttsDeviceEnabled/ttsMuted (sonst stale).
|
||||
useEffect(() => {
|
||||
@@ -569,16 +588,16 @@ const ChatScreen: React.FC = () => {
|
||||
|
||||
// TTS-Lifecycle: solange ARIA spricht und Wake-Word verfuegbar ist,
|
||||
// parallel mitlauschen — User kann "Computer" sagen statt manuell tappen.
|
||||
// PLUS: Foreground-Service starten damit Android den App-Prozess nicht
|
||||
// killt wenn die App im Hintergrund ist (TTS waere sonst mitten im Satz weg).
|
||||
// PLUS: Foreground-Service-Slot 'tts' belegen damit Android den App-
|
||||
// Prozess nicht killt wenn die App im Hintergrund ist.
|
||||
const unsubTtsStart = audioService.onPlaybackStarted(() => {
|
||||
startBackgroundAudio().catch(() => {});
|
||||
acquireBackgroundAudio('tts').catch(() => {});
|
||||
if (wakeWordService.isConversing() && wakeWordService.hasWakeWord()) {
|
||||
wakeWordService.startBargeListening().catch(() => {});
|
||||
}
|
||||
});
|
||||
const unsubTtsEnd = audioService.onPlaybackFinished(() => {
|
||||
stopBackgroundAudio().catch(() => {});
|
||||
releaseBackgroundAudio('tts').catch(() => {});
|
||||
// Vor naechster Aufnahme: barge-listening aus damit der AudioRecorder
|
||||
// das Mikro greifen kann.
|
||||
wakeWordService.stopBargeListening().catch(() => {});
|
||||
|
||||
Reference in New Issue
Block a user