import 'package:flutter/services.dart'; import 'streaming_audio_business_object.dart'; class CarPlayBridge { CarPlayBridge({required StreamingAudioBusinessObject audio}) : _audio = audio; static const MethodChannel _channel = MethodChannel( 'kryz_go_flutter/carplay/methods', ); final StreamingAudioBusinessObject _audio; bool _isStarted = false; Future start() async { if (_isStarted) { return; } _isStarted = true; _channel.setMethodCallHandler(_handleNativeMethodCall); _audio.addListener(_onAudioChanged); await _pushSnapshotToNative(); } Future dispose() async { if (!_isStarted) { return; } _isStarted = false; _audio.removeListener(_onAudioChanged); _channel.setMethodCallHandler(null); } Map _snapshot() { final String playbackStatus = switch (_audio.playbackStatus) { StreamingPlaybackStatus.playing => 'playing', StreamingPlaybackStatus.buffering => 'buffering', StreamingPlaybackStatus.stopped => 'stopped', }; return { 'playbackStatus': playbackStatus, 'isPlaying': _audio.isPlaying, 'isBuffering': _audio.isBuffering, 'isLive': true, 'seekable': false, 'title': _audio.currentTitle, 'subtitle': _audio.currentSubtitle, 'album': 'Live', }; } Future _handleNativeMethodCall(MethodCall call) async { switch (call.method) { case 'getStateSnapshot': return _snapshot(); default: throw MissingPluginException('Unknown CarPlay bridge method: ${call.method}'); } } void _onAudioChanged() { _pushSnapshotToNative(); } Future _pushSnapshotToNative() async { try { await _channel.invokeMethod('syncState', _snapshot()); } on MissingPluginException { // CarPlay bridge only exists on iOS native builds. } on PlatformException { // Keep playback working even if native sync temporarily fails. } } }