Compare commits

..

4 Commits

Author SHA1 Message Date
duffyduck a0570ef8f7 release: bump version to 0.1.0.7 2026-05-10 17:14:11 +02:00
duffyduck facde1fef7 fix(audio): kickReleaseMedia auch im PCM-Pfad — re-renderte Antworten muteten Spotify dauerhaft
Stefan: ältere Nachrichten (deren Cache-WAV weg ist) gehen ueber
tts_request neu rendern → kommen als PCM-Stream zurueck → werden ueber
PcmStreamPlayer abgespielt. Beim Mute lief stopPlayback aber ohne den
Spotify-resume-Kick weil hadRnSound=false war (kein currentSound).

Jetzt: kickReleaseMedia immer in stopPlayback rufen — kostet nichts,
deckt PCM- und RNSound-Pfad ab.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 17:13:12 +02:00
duffyduck 38106a2096 release: bump version to 0.1.0.6 2026-05-10 17:07:53 +02:00
duffyduck a476afb311 fix(audio): kickReleaseMedia mit 250ms Pause zwischen request+abandon — Spotify kriegt den Focus-Wechsel sonst gar nicht mit
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 17:07:03 +02:00
4 changed files with 39 additions and 38 deletions
+2 -2
View File
@@ -79,8 +79,8 @@ android {
applicationId "com.ariacockpit" applicationId "com.ariacockpit"
minSdkVersion rootProject.ext.minSdkVersion minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 10005 versionCode 10007
versionName "0.1.0.5" versionName "0.1.0.7"
// Fallback fuer Libraries mit Product Flavors // Fallback fuer Libraries mit Product Flavors
missingDimensionStrategy 'react-native-camera', 'general' missingDimensionStrategy 'react-native-camera', 'general'
} }
@@ -148,33 +148,39 @@ class AudioFocusModule(reactContext: ReactApplicationContext) : ReactContextBase
promise.resolve(false) promise.resolve(false)
return return
} }
try { // Async laufen lassen — wir wollen einen request, Pause, dann abandon.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // Ohne Pause merkt das System (und damit Spotify) die kurze Owner-
val attrs = AudioAttributes.Builder() // Wechsel oft gar nicht. 250ms reicht erfahrungsgemaess fuer den
.setUsage(AudioAttributes.USAGE_MEDIA) // Focus-Stack-Refresh.
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) Thread {
.build() try {
val kickListener = AudioManager.OnAudioFocusChangeListener { /* ignorieren */ } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val kickReq = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN) val attrs = AudioAttributes.Builder()
.setAudioAttributes(attrs) .setUsage(AudioAttributes.USAGE_MEDIA)
.setOnAudioFocusChangeListener(kickListener) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build() .build()
am.requestAudioFocus(kickReq) val kickListener = AudioManager.OnAudioFocusChangeListener { /* ignorieren */ }
am.abandonAudioFocusRequest(kickReq) val kickReq = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
} else { .setAudioAttributes(attrs)
@Suppress("DEPRECATION") .setOnAudioFocusChangeListener(kickListener)
val kickListener = AudioManager.OnAudioFocusChangeListener { /* ignorieren */ } .build()
@Suppress("DEPRECATION") am.requestAudioFocus(kickReq)
am.requestAudioFocus(kickListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN) Thread.sleep(250)
@Suppress("DEPRECATION") am.abandonAudioFocusRequest(kickReq)
am.abandonAudioFocus(kickListener) } else {
val kickListener = AudioManager.OnAudioFocusChangeListener { /* ignorieren */ }
@Suppress("DEPRECATION")
am.requestAudioFocus(kickListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN)
Thread.sleep(250)
@Suppress("DEPRECATION")
am.abandonAudioFocus(kickListener)
}
Log.i(TAG, "kickReleaseMedia: USAGE_MEDIA-Stack aufgemischt (250ms Pause)")
} catch (e: Exception) {
Log.w(TAG, "kickReleaseMedia failed: ${e.message}")
} }
Log.i(TAG, "kickReleaseMedia: USAGE_MEDIA-Stack aufgemischt") }.start()
promise.resolve(true) promise.resolve(true)
} catch (e: Exception) {
Log.w(TAG, "kickReleaseMedia failed: ${e.message}")
promise.resolve(false)
}
} }
private fun release() { private fun release() {
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "aria-cockpit", "name": "aria-cockpit",
"version": "0.1.0.5", "version": "0.1.0.7",
"private": true, "private": true,
"scripts": { "scripts": {
"android": "react-native run-android", "android": "react-native run-android",
+4 -9
View File
@@ -1204,10 +1204,6 @@ class AudioService {
stopBackgroundAudio().catch(() => {}); stopBackgroundAudio().catch(() => {});
this.audioQueue = []; this.audioQueue = [];
this.isPlaying = false; this.isPlaying = false;
// Merken: war ein react-native-sound-Sound aktiv? Dann muessen wir nach
// release() den Focus-Stack aufmischen (RNSound-Bug: stop+release laesst
// den AudioFocusRequest haengen, Spotify resumed sonst nicht).
const hadRnSound = !!(this.currentSound || this.resumeSound || this.preloadedSound);
if (this.currentSound) { if (this.currentSound) {
this.currentSound.stop(); this.currentSound.stop();
this.currentSound.release(); this.currentSound.release();
@@ -1236,11 +1232,10 @@ class AudioService {
// Audio-Focus sofort freigeben — User hat explizit abgebrochen // Audio-Focus sofort freigeben — User hat explizit abgebrochen
this._cancelDeferredFocusRelease(); this._cancelDeferredFocusRelease();
AudioFocus?.release().catch(() => {}); AudioFocus?.release().catch(() => {});
if (hadRnSound) { // Focus-Stack immer aufmischen — bei aelteren Nachrichten die ueber
// RNSound's haengender USAGE_MEDIA-Focus aufloesen — sonst bleibt // tts_request (PCM-Stream) re-rendert wurden, bleibt Spotify ohne den
// Spotify pausiert obwohl unser Focus released ist. // Kick auch pausiert. Kostet nichts, deckt beide Pfade ab.
AudioFocus?.kickReleaseMedia?.().catch(() => {}); AudioFocus?.kickReleaseMedia?.().catch(() => {});
}
} }
// --- Status & Callbacks --- // --- Status & Callbacks ---