fix(calls): Bildschirmübertragung ohne Absturz, Lautsprecher, Mikrofon im Hintergrund, zurück in den Anruf
Bernds Anruftest Handy↔PC (2026-10-07): - Teilen am Handy: App "verkleinerte sich", Anruf danach weg. Ursache: Android 14+ verlangt vor MediaProjection einen Vordergrunddienst vom Typ mediaProjection; flutter_webrtc startet keinen, der Manifest-Eintrag verwies auf eine nicht mehr existierende Klasse. Neu: CallService (microphone|mediaProjection) + CallForeground: Zustimmung → Dienst (wartet auf echten startForeground) → Mitschnitt. Emulator-Test (Android 16): mit Fix 1080x2400@30 läuft; Gegenprobe ohne Dienst wirft genau 'Media projections require a foreground service ...'. - Dienst läuft während jedes Anrufs: Mikrofon bleibt im Hintergrund aktiv, Benachrichtigung "Anruf läuft" führt zurück. Mikrofon-Typ nur mit Berechtigung, sonst schmalere Variante statt Dienst-Abbruch. - Handy hörte nichts: SDK schaltet Sprachanrufe auf die Hörmuschel. Jetzt Lautsprecher als Standard (wie Discord) + Umschalter in der Anrufleiste. - LiveKit-Teilen am Handy öffnete den PC-Quellen-Auswähler → System-Dialog. - Im offenen Chat (Handy) Leiste "Anruf läuft · Zurück". - Einstellungen → Sprache & Video: Mikrofontest mit Pegel (PC-Diagnose: das Standardgerät lieferte nur Stille – Voicemeeter/virtuelle Geräte). Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
c817de924a
commit
441cc6ef54
@@ -4,6 +4,7 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc;
|
||||
import 'package:livekit_client/livekit_client.dart';
|
||||
import 'package:matrix/matrix.dart' hide Room;
|
||||
import 'package:pyramid/core/call_foreground.dart';
|
||||
import 'package:pyramid/core/ice_servers.dart';
|
||||
import 'package:pyramid/core/livekit_token.dart';
|
||||
import 'package:pyramid/core/settings_prefs.dart';
|
||||
@@ -98,8 +99,35 @@ class LiveKitCallManager extends VoiceChannelService {
|
||||
|
||||
void _onRoomChanged() => notifyListeners();
|
||||
|
||||
// Handy: Lautsprecher statt Hörmuschel (wie Discord).
|
||||
bool _speakerOn = true;
|
||||
bool get _isMobile =>
|
||||
!kIsWeb &&
|
||||
(defaultTargetPlatform == TargetPlatform.android ||
|
||||
defaultTargetPlatform == TargetPlatform.iOS);
|
||||
|
||||
@override
|
||||
bool get isSpeakerOn => _speakerOn;
|
||||
|
||||
@override
|
||||
Future<void> toggleSpeaker() async {
|
||||
_speakerOn = !_speakerOn;
|
||||
notifyListeners();
|
||||
await _applySpeaker();
|
||||
}
|
||||
|
||||
Future<void> _applySpeaker() async {
|
||||
if (!_isMobile) return;
|
||||
try {
|
||||
await rtc.Helper.setSpeakerphoneOn(_speakerOn);
|
||||
} catch (e) {
|
||||
debugPrint('[LiveKit] Lautsprecher: $e');
|
||||
}
|
||||
}
|
||||
|
||||
void _cleanUpAfterDisconnect() {
|
||||
_callGeneration++;
|
||||
CallForeground.callEnded('livekit');
|
||||
_stopStatsLogging();
|
||||
_presenceHeartbeat?.cancel();
|
||||
_presenceHeartbeat = null;
|
||||
@@ -254,6 +282,10 @@ class LiveKitCallManager extends VoiceChannelService {
|
||||
_room = room;
|
||||
isConnecting = false;
|
||||
notifyListeners();
|
||||
_speakerOn = true;
|
||||
unawaited(_applySpeaker());
|
||||
// Android: Mikrofon im Hintergrund + „Anruf läuft“-Benachrichtigung.
|
||||
unawaited(CallForeground.callStarted('livekit', title: roomDisplayName));
|
||||
|
||||
if (voiceChannel && matrixClient != null && matrixRoomId != null) {
|
||||
await _writePresence(true);
|
||||
@@ -269,6 +301,7 @@ class LiveKitCallManager extends VoiceChannelService {
|
||||
isScreenSharing = false;
|
||||
_currentScreenShareSourceId = null;
|
||||
_screenShareTrack = null;
|
||||
CallForeground.screenCaptureStopped('livekit');
|
||||
}
|
||||
notifyListeners();
|
||||
})
|
||||
@@ -487,6 +520,11 @@ class LiveKitCallManager extends VoiceChannelService {
|
||||
}
|
||||
}
|
||||
|
||||
// Android 14+: erst Zustimmung + mediaProjection-Dienst, sonst
|
||||
// stürzt die App beim Mitschnitt ab.
|
||||
if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
|
||||
if (!await CallForeground.prepareScreenCapture('livekit')) return;
|
||||
}
|
||||
await _room?.localParticipant?.setScreenShareEnabled(true);
|
||||
isScreenSharing = true;
|
||||
notifyListeners();
|
||||
@@ -587,6 +625,7 @@ class LiveKitCallManager extends VoiceChannelService {
|
||||
}
|
||||
}
|
||||
try { await _room?.localParticipant?.setScreenShareEnabled(false); } catch (_) {}
|
||||
await CallForeground.screenCaptureStopped('livekit');
|
||||
isScreenSharing = false;
|
||||
_currentScreenShareSourceId = null;
|
||||
_screenShareTrack = null;
|
||||
@@ -597,6 +636,7 @@ class LiveKitCallManager extends VoiceChannelService {
|
||||
Future<void> hangUp() async {
|
||||
// Entwertet einen evtl. noch laufenden Verbindungsaufbau (s. _callGeneration).
|
||||
_callGeneration++;
|
||||
unawaited(CallForeground.callEnded('livekit'));
|
||||
_stopStatsLogging();
|
||||
_presenceHeartbeat?.cancel();
|
||||
_presenceHeartbeat = null;
|
||||
|
||||
Reference in New Issue
Block a user