diff --git a/melos.yaml b/melos.yaml
index a04e3758f5e5..8fe40bdfc22d 100644
--- a/melos.yaml
+++ b/melos.yaml
@@ -290,6 +290,10 @@ scripts:
         --ignore "**/generated/**" \
         --ignore "**/flutter/generated_plugin_registrant.h" \
         --ignore "**/flutter/generated_plugin_registrant.cc" \
+        --ignore "**/android/app/build.gradle.kts" \
+        --ignore "**/android/build.gradle.kts" \
+        --ignore "**/android/settings.gradle.kts" \
+        --ignore "**/RunnerTests/RunnerTests.swift" \
         .
     description: Add a license header to all necessary files.
 
@@ -326,6 +330,10 @@ scripts:
         --ignore "**/generated/**" \
         --ignore "**/flutter/generated_plugin_registrant.h" \
         --ignore "**/flutter/generated_plugin_registrant.cc" \
+        --ignore "**/android/app/build.gradle.kts" \
+        --ignore "**/android/build.gradle.kts" \
+        --ignore "**/android/settings.gradle.kts" \
+        --ignore "**/RunnerTests/RunnerTests.swift" \
         .
     description: Add a license header to all necessary files.
 
diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/bidi_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/bidi_page.dart
index acd936a7e827..cb221329d28f 100644
--- a/packages/firebase_ai/firebase_ai/example/lib/pages/bidi_page.dart
+++ b/packages/firebase_ai/firebase_ai/example/lib/pages/bidi_page.dart
@@ -11,15 +11,15 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
-import 'dart:typed_data';
 import 'dart:async';
-import 'dart:developer';
+import 'dart:developer' as developer;
 
 import 'package:flutter/material.dart';
 import 'package:firebase_ai/firebase_ai.dart';
+
+import '../utils/audio_input.dart';
+import '../utils/audio_output.dart';
 import '../widgets/message_widget.dart';
-import '../utils/audio_player.dart';
-import '../utils/audio_recorder.dart';
 
 class BidiPage extends StatefulWidget {
   const BidiPage({super.key, required this.title, required this.model});
@@ -48,11 +48,9 @@ class _BidiPageState extends State<BidiPage> {
   bool _recording = false;
   late LiveGenerativeModel _liveModel;
   late LiveSession _session;
-  final _audioManager = AudioStreamManager();
-  final _audioRecorder = InMemoryAudioRecorder();
-  var _chunkBuilder = BytesBuilder();
-  var _audioIndex = 0;
   StreamController<bool> _stopController = StreamController<bool>();
+  final AudioOutput _audioOutput = AudioOutput();
+  final AudioInput _audioInput = AudioInput();
 
   @override
   void initState() {
@@ -65,6 +63,7 @@ class _BidiPageState extends State<BidiPage> {
       ],
     );
 
+    // ignore: deprecated_member_use
     _liveModel = FirebaseAI.vertexAI().liveGenerativeModel(
       model: 'gemini-2.0-flash-exp',
       liveGenerationConfig: config,
@@ -72,6 +71,12 @@ class _BidiPageState extends State<BidiPage> {
         Tool.functionDeclarations([lightControlTool]),
       ],
     );
+    _initAudio();
+  }
+
+  Future<void> _initAudio() async {
+    await _audioOutput.init();
+    await _audioInput.init();
   }
 
   void _scrollDown() {
@@ -89,13 +94,7 @@ class _BidiPageState extends State<BidiPage> {
   @override
   void dispose() {
     if (_sessionOpening) {
-      _audioManager.stopAudioPlayer();
-      _audioManager.disposeAudioPlayer();
-
-      _audioRecorder.stopRecording();
-
       _stopController.close();
-
       _sessionOpening = false;
       _session.close();
     }
@@ -234,7 +233,7 @@ class _BidiPageState extends State<BidiPage> {
       _sessionOpening = true;
       _stopController = StreamController<bool>();
       unawaited(
-        processMessagesContinuously(
+        _processMessagesContinuously(
           stopSignal: _stopController,
         ),
       );
@@ -243,8 +242,6 @@ class _BidiPageState extends State<BidiPage> {
       await _stopController.close();
 
       await _session.close();
-      await _audioManager.stopAudioPlayer();
-      await _audioManager.disposeAudioPlayer();
       _sessionOpening = false;
     }
 
@@ -258,21 +255,25 @@ class _BidiPageState extends State<BidiPage> {
       _recording = true;
     });
     try {
-      await _audioRecorder.checkPermission();
-      final audioRecordStream = _audioRecorder.startRecordingStream();
+      var inputStream = await _audioInput.startRecordingStream();
+      await _audioOutput.playStream();
       // Map the Uint8List stream to InlineDataPart stream
-      final mediaChunkStream = audioRecordStream.map((data) {
-        return InlineDataPart('audio/pcm', data);
-      });
-      await _session.sendMediaStream(mediaChunkStream);
+      if (inputStream != null) {
+        final inlineDataStream = inputStream.map((data) {
+          return InlineDataPart('audio/pcm', data);
+        });
+
+        await _session.sendMediaStream(inlineDataStream);
+      }
     } catch (e) {
+      developer.log(e.toString());
       _showError(e.toString());
     }
   }
 
   Future<void> _stopRecording() async {
     try {
-      await _audioRecorder.stopRecording();
+      await _audioInput.stopRecording();
     } catch (e) {
       _showError(e.toString());
     }
@@ -298,7 +299,7 @@ class _BidiPageState extends State<BidiPage> {
     });
   }
 
-  Future<void> processMessagesContinuously({
+  Future<void> _processMessagesContinuously({
     required StreamController<bool> stopSignal,
   }) async {
     bool shouldContinue = true;
@@ -335,11 +336,8 @@ class _BidiPageState extends State<BidiPage> {
       if (message.modelTurn != null) {
         await _handleLiveServerContent(message);
       }
-      if (message.turnComplete != null && message.turnComplete!) {
-        await _handleTurnComplete();
-      }
       if (message.interrupted != null && message.interrupted!) {
-        log('Interrupted: $response');
+        developer.log('Interrupted: $response');
       }
     } else if (message is LiveServerToolCall && message.functionCalls != null) {
       await _handleLiveServerToolCall(message);
@@ -355,7 +353,7 @@ class _BidiPageState extends State<BidiPage> {
         } else if (part is InlineDataPart) {
           await _handleInlineDataPart(part);
         } else {
-          log('receive part with type ${part.runtimeType}');
+          developer.log('receive part with type ${part.runtimeType}');
         }
       }
     }
@@ -376,29 +374,7 @@ class _BidiPageState extends State<BidiPage> {
 
   Future<void> _handleInlineDataPart(InlineDataPart part) async {
     if (part.mimeType.startsWith('audio')) {
-      _chunkBuilder.add(part.bytes);
-      _audioIndex++;
-      if (_audioIndex == 15) {
-        Uint8List chunk = await audioChunkWithHeader(
-          _chunkBuilder.toBytes(),
-          24000,
-        );
-        _audioManager.addAudio(chunk);
-        _chunkBuilder.clear();
-        _audioIndex = 0;
-      }
-    }
-  }
-
-  Future<void> _handleTurnComplete() async {
-    if (_chunkBuilder.isNotEmpty) {
-      Uint8List chunk = await audioChunkWithHeader(
-        _chunkBuilder.toBytes(),
-        24000,
-      );
-      _audioManager.addAudio(chunk);
-      _audioIndex = 0;
-      _chunkBuilder.clear();
+      _audioOutput.addAudioStream(part.bytes);
     }
   }
 
diff --git a/packages/firebase_ai/firebase_ai/example/lib/utils/audio_input.dart b/packages/firebase_ai/firebase_ai/example/lib/utils/audio_input.dart
new file mode 100644
index 000000000000..869d4ee32781
--- /dev/null
+++ b/packages/firebase_ai/firebase_ai/example/lib/utils/audio_input.dart
@@ -0,0 +1,95 @@
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'package:flutter/material.dart';
+import 'package:record/record.dart';
+import 'dart:typed_data';
+
+class AudioInput extends ChangeNotifier {
+  final _recorder = AudioRecorder();
+  final AudioEncoder _encoder = AudioEncoder.pcm16bits;
+  bool isRecording = false;
+  bool isPaused = false;
+  Stream<Uint8List>? audioStream;
+
+  Future<void> init() async {
+    await _checkPermission();
+  }
+
+  @override
+  void dispose() {
+    _recorder.dispose();
+    super.dispose();
+  }
+
+  Future<void> _checkPermission() async {
+    final hasPermission = await _recorder.hasPermission();
+    if (!hasPermission) {
+      throw MicrophonePermissionDeniedException(
+        'App does not have mic permissions',
+      );
+    }
+  }
+
+  Future<Stream<Uint8List>?> startRecordingStream() async {
+    var recordConfig = RecordConfig(
+      encoder: _encoder,
+      sampleRate: 24000,
+      numChannels: 1,
+      echoCancel: true,
+      noiseSuppress: true,
+      androidConfig: const AndroidRecordConfig(
+        audioSource: AndroidAudioSource.voiceCommunication,
+      ),
+      iosConfig: const IosRecordConfig(categoryOptions: []),
+    );
+    await _recorder.listInputDevices();
+    audioStream = await _recorder.startStream(recordConfig);
+    isRecording = true;
+    notifyListeners();
+    return audioStream;
+  }
+
+  Future<void> stopRecording() async {
+    await _recorder.stop();
+    isRecording = false;
+    notifyListeners();
+  }
+
+  Future<void> togglePause() async {
+    if (isPaused) {
+      await _recorder.resume();
+      isPaused = false;
+    } else {
+      await _recorder.pause();
+      isPaused = true;
+    }
+    notifyListeners();
+    return;
+  }
+}
+
+/// An exception thrown when microphone permission is denied or not granted.
+class MicrophonePermissionDeniedException implements Exception {
+  /// The optional message associated with the permission denial.
+  final String? message;
+
+  /// Creates a new [MicrophonePermissionDeniedException] with an optional [message].
+  MicrophonePermissionDeniedException([this.message]);
+
+  @override
+  String toString() {
+    return 'MicrophonePermissionDeniedException: $message';
+  }
+}
diff --git a/packages/firebase_ai/firebase_ai/example/lib/utils/audio_output.dart b/packages/firebase_ai/firebase_ai/example/lib/utils/audio_output.dart
new file mode 100644
index 000000000000..b97ad3478f5b
--- /dev/null
+++ b/packages/firebase_ai/firebase_ai/example/lib/utils/audio_output.dart
@@ -0,0 +1,66 @@
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'dart:typed_data';
+
+import 'package:flutter_soloud/flutter_soloud.dart';
+
+class AudioOutput {
+  AudioSource? stream;
+  SoundHandle? handle;
+
+  Future<void> init() async {
+    // Initialize the player.
+    await SoLoud.instance.init(sampleRate: 24000, channels: Channels.mono);
+    await setupNewStream();
+  }
+
+  Future<void> setupNewStream() async {
+    if (SoLoud.instance.isInitialized) {
+      // Stop and clear any previous playback handle if it's still valid
+      await stopStream(); // Ensure previous sound is stopped
+
+      stream = SoLoud.instance.setBufferStream(
+        maxBufferSizeBytes:
+            1024 * 1024 * 10, // 10MB of max buffer (not allocated)
+        bufferingType: BufferingType.released,
+        bufferingTimeNeeds: 0,
+        onBuffering: (isBuffering, handle, time) {},
+      );
+      // Reset handle to null until the stream is played again
+      handle = null;
+    }
+  }
+
+  Future<AudioSource?> playStream() async {
+    handle = await SoLoud.instance.play(stream!);
+    return stream;
+  }
+
+  Future<void> stopStream() async {
+    if (stream != null &&
+        handle != null &&
+        SoLoud.instance.getIsValidVoiceHandle(handle!)) {
+      SoLoud.instance.setDataIsEnded(stream!);
+      await SoLoud.instance.stop(handle!);
+
+      // Clear old stream, set up new session for next time.
+      await setupNewStream();
+    }
+  }
+
+  void addAudioStream(Uint8List audioChunk) {
+    SoLoud.instance.addAudioDataStream(stream!, audioChunk);
+  }
+}
diff --git a/packages/firebase_ai/firebase_ai/example/lib/utils/audio_player.dart b/packages/firebase_ai/firebase_ai/example/lib/utils/audio_player.dart
deleted file mode 100644
index 3c5559481ed7..000000000000
--- a/packages/firebase_ai/firebase_ai/example/lib/utils/audio_player.dart
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2025 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import 'dart:typed_data';
-import 'dart:async';
-
-import 'package:just_audio/just_audio.dart';
-
-/// Creates a WAV audio chunk with a properly formatted header.
-Future<Uint8List> audioChunkWithHeader(
-  List<int> data,
-  int sampleRate,
-) async {
-  var channels = 1;
-
-  int byteRate = ((16 * sampleRate * channels) / 8).round();
-
-  var size = data.length;
-  var fileSize = size + 36;
-
-  Uint8List header = Uint8List.fromList([
-    // "RIFF"
-    82, 73, 70, 70,
-    fileSize & 0xff,
-    (fileSize >> 8) & 0xff,
-    (fileSize >> 16) & 0xff,
-    (fileSize >> 24) & 0xff,
-    // WAVE
-    87, 65, 86, 69,
-    // fmt
-    102, 109, 116, 32,
-    // fmt chunk size 16
-    16, 0, 0, 0,
-    // Type of format
-    1, 0,
-    // One channel
-    channels, 0,
-    // Sample rate
-    sampleRate & 0xff,
-    (sampleRate >> 8) & 0xff,
-    (sampleRate >> 16) & 0xff,
-    (sampleRate >> 24) & 0xff,
-    // Byte rate
-    byteRate & 0xff,
-    (byteRate >> 8) & 0xff,
-    (byteRate >> 16) & 0xff,
-    (byteRate >> 24) & 0xff,
-    // Uhm
-    ((16 * channels) / 8).round(), 0,
-    // bitsize
-    16, 0,
-    // "data"
-    100, 97, 116, 97,
-    size & 0xff,
-    (size >> 8) & 0xff,
-    (size >> 16) & 0xff,
-    (size >> 24) & 0xff,
-    // incoming data
-    ...data,
-  ]);
-  return header;
-}
-
-class ByteStreamAudioSource extends StreamAudioSource {
-  ByteStreamAudioSource(this.bytes) : super(tag: 'Byte Stream Audio');
-
-  final Uint8List bytes;
-
-  @override
-  Future<StreamAudioResponse> request([int? start, int? end]) async {
-    start ??= 0;
-    end ??= bytes.length;
-    return StreamAudioResponse(
-      sourceLength: bytes.length,
-      contentLength: end - start,
-      offset: start,
-      stream: Stream.value(bytes.sublist(start, end)),
-      contentType: 'audio/wav', // Or the appropriate content type
-    );
-  }
-}
-
-class AudioStreamManager {
-  final _audioPlayer = AudioPlayer();
-  final _audioChunkController = StreamController<Uint8List>();
-  var _audioSource = ConcatenatingAudioSource(
-    children: [],
-  );
-
-  AudioStreamManager() {
-    _initAudioPlayer();
-  }
-
-  Future<void> _initAudioPlayer() async {
-    // 1. Create a ConcatenatingAudioSource to handle the stream
-    await _audioPlayer.setAudioSource(_audioSource);
-
-    // 2. Listen to the stream of audio chunks
-    _audioChunkController.stream.listen(_addAudioChunk);
-
-    await _audioPlayer.play(); // Start playing (even if initially empty)
-
-    _audioPlayer.processingStateStream.listen((state) async {
-      if (state == ProcessingState.completed) {
-        await _audioPlayer
-            .pause(); // Or player.stop() if you want to release resources
-        await _audioPlayer.seek(Duration.zero, index: 0);
-        await _audioSource.clear();
-        await _audioPlayer.play();
-      }
-    });
-  }
-
-  Future<void> _addAudioChunk(Uint8List chunk) async {
-    var buffer = ByteStreamAudioSource(chunk);
-
-    await _audioSource.add(buffer);
-  }
-
-  void addAudio(Uint8List chunk) {
-    _audioChunkController.add(chunk);
-  }
-
-  Future<void> stopAudioPlayer() async {
-    await _audioPlayer.stop();
-  }
-
-  Future<void> disposeAudioPlayer() async {
-    await _audioPlayer.dispose();
-    await _audioChunkController.close();
-  }
-}
diff --git a/packages/firebase_ai/firebase_ai/example/lib/utils/audio_recorder.dart b/packages/firebase_ai/firebase_ai/example/lib/utils/audio_recorder.dart
deleted file mode 100644
index 1f3710cd0c8f..000000000000
--- a/packages/firebase_ai/firebase_ai/example/lib/utils/audio_recorder.dart
+++ /dev/null
@@ -1,245 +0,0 @@
-// Copyright 2025 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import 'dart:async';
-import 'dart:io';
-import 'dart:typed_data';
-
-import 'package:flutter/material.dart';
-import 'package:path_provider/path_provider.dart';
-import 'package:record/record.dart';
-
-/// An exception thrown when microphone permission is denied or not granted.
-class MicrophonePermissionDeniedException implements Exception {
-  /// The optional message associated with the permission denial.
-  final String? message;
-
-  /// Creates a new [MicrophonePermissionDeniedException] with an optional [message].
-  MicrophonePermissionDeniedException([this.message]);
-
-  @override
-  String toString() {
-    if (message == null) {
-      return 'MicrophonePermissionDeniedException';
-    }
-    return 'MicrophonePermissionDeniedException: $message';
-  }
-}
-
-class Resampler {
-  /// Resamples 16-bit integer PCM audio data from a source sample rate to a
-  /// target sample rate using linear interpolation.
-  ///
-  /// [sourceRate]: The sample rate of the input audio data.
-  /// [targetRate]: The desired sample rate of the output audio data.
-  /// [input]: The input audio data as a Uint8List containing 16-bit PCM samples.
-  ///
-  /// Returns a new Uint8List containing 16-bit PCM samples resampled to the
-  /// target rate.
-  static Uint8List resampleLinear16(
-    int sourceRate,
-    int targetRate,
-    Uint8List input,
-  ) {
-    if (sourceRate == targetRate) return input; // No resampling needed
-
-    final outputLength = (input.length * targetRate / sourceRate).round();
-    final output = Uint8List(outputLength);
-    final inputData = Int16List.view(input.buffer);
-    final outputData = Int16List.view(output.buffer);
-
-    for (int i = 0; i < outputLength ~/ 2; i++) {
-      final sourcePosition = i * sourceRate / targetRate;
-      final index1 = sourcePosition.floor();
-      final index2 = index1 + 1;
-      final weight2 = sourcePosition - index1;
-      final weight1 = 1.0 - weight2;
-
-      // Ensure indices are within the valid range
-      final sample1 = inputData[index1.clamp(0, inputData.length - 1)];
-      final sample2 = inputData[index2.clamp(0, inputData.length - 1)];
-
-      // Interpolate and convert back to 16-bit integer
-      final interpolatedSample =
-          (sample1 * weight1 + sample2 * weight2).toInt();
-
-      outputData[i] = interpolatedSample;
-    }
-
-    return output;
-  }
-}
-
-class InMemoryAudioRecorder {
-  final _audioChunks = <Uint8List>[];
-  final _recorder = AudioRecorder();
-  StreamSubscription<Uint8List>? _recordSubscription;
-  late String? _lastAudioPath;
-  AudioEncoder _encoder = AudioEncoder.pcm16bits;
-
-  Future<String> _getPath() async {
-    String suffix;
-    if (_encoder == AudioEncoder.pcm16bits) {
-      suffix = 'pcm';
-    } else if (_encoder == AudioEncoder.aacLc) {
-      suffix = 'm4a';
-    } else {
-      suffix = 'wav';
-    }
-    final dir = await getDownloadsDirectory();
-    final path =
-        '${dir!.path}/audio_${DateTime.now().millisecondsSinceEpoch}.$suffix';
-    return path;
-  }
-
-  Future<void> checkPermission() async {
-    final hasPermission = await _recorder.hasPermission();
-    if (!hasPermission) {
-      throw MicrophonePermissionDeniedException('Not having mic permission');
-    }
-  }
-
-  Future<bool> _isEncoderSupported(AudioEncoder encoder) async {
-    final isSupported = await _recorder.isEncoderSupported(
-      encoder,
-    );
-
-    if (!isSupported) {
-      debugPrint('${encoder.name} is not supported on this platform.');
-      debugPrint('Supported encoders are:');
-
-      for (final e in AudioEncoder.values) {
-        if (await _recorder.isEncoderSupported(e)) {
-          debugPrint('- ${e.name}');
-        }
-      }
-    }
-
-    return isSupported;
-  }
-
-  Future<void> startRecording({bool fromFile = false}) async {
-    if (!await _isEncoderSupported(_encoder)) {
-      return;
-    }
-    var recordConfig = RecordConfig(
-      encoder: _encoder,
-      sampleRate: 16000,
-      numChannels: 1,
-      androidConfig: const AndroidRecordConfig(
-        muteAudio: true,
-        audioSource: AndroidAudioSource.mic,
-      ),
-    );
-    final devs = await _recorder.listInputDevices();
-    debugPrint(devs.toString());
-    _lastAudioPath = await _getPath();
-    if (fromFile) {
-      await _recorder.start(recordConfig, path: _lastAudioPath!);
-    } else {
-      final stream = await _recorder.startStream(recordConfig);
-      _recordSubscription = stream.listen(_audioChunks.add);
-    }
-  }
-
-  Future<void> startRecordingFile() async {
-    if (!await _isEncoderSupported(_encoder)) {
-      return;
-    }
-    var recordConfig = RecordConfig(
-      encoder: _encoder,
-      sampleRate: 16000,
-      numChannels: 1,
-    );
-    final devs = await _recorder.listInputDevices();
-    debugPrint(devs.toString());
-    _lastAudioPath = await _getPath();
-    await _recorder.start(recordConfig, path: _lastAudioPath!);
-  }
-
-  Stream<Uint8List> startRecordingStream() async* {
-    if (!await _isEncoderSupported(_encoder)) {
-      return;
-    }
-    var recordConfig = RecordConfig(
-      encoder: _encoder,
-      sampleRate: 16000,
-      numChannels: 1,
-    );
-    final devices = await _recorder.listInputDevices();
-    debugPrint(devices.toString());
-    final stream = await _recorder.startStream(recordConfig);
-
-    await for (final data in stream) {
-      yield data;
-    }
-  }
-
-  Future<void> stopRecording() async {
-    await _recordSubscription?.cancel();
-    _recordSubscription = null;
-
-    await _recorder.stop();
-  }
-
-  Future<Uint8List> fetchAudioBytes({
-    bool fromFile = false,
-    bool removeHeader = false,
-  }) async {
-    Uint8List resultBytes;
-    if (fromFile) {
-      resultBytes = await _getAudioBytesFromFile(_lastAudioPath!);
-    } else {
-      final builder = BytesBuilder();
-      _audioChunks.forEach(builder.add);
-      resultBytes = builder.toBytes();
-    }
-
-    // resample
-    resultBytes = Resampler.resampleLinear16(44100, 16000, resultBytes);
-    final dir = await getDownloadsDirectory();
-    final path = '${dir!.path}/audio_resampled.pcm';
-    final file = File(path);
-    final sink = file.openWrite();
-
-    sink.add(resultBytes);
-
-    await sink.close();
-    return resultBytes;
-  }
-
-  Future<Uint8List> _removeWavHeader(Uint8List audio) async {
-    // Assuming a standard WAV header size of 44 bytes
-    const wavHeaderSize = 44;
-    final audioData = audio.sublist(wavHeaderSize);
-    return audioData;
-  }
-
-  Future<Uint8List> _getAudioBytesFromFile(
-    String filePath, {
-    bool removeHeader = false,
-  }) async {
-    final file = File(_lastAudioPath!);
-
-    if (!file.existsSync()) {
-      throw Exception('Audio file not found: ${file.path}');
-    }
-
-    var pcmBytes = await file.readAsBytes();
-    if (removeHeader) {
-      pcmBytes = await _removeWavHeader(pcmBytes);
-    }
-    return pcmBytes;
-  }
-}
diff --git a/packages/firebase_ai/firebase_ai/example/pubspec.yaml b/packages/firebase_ai/firebase_ai/example/pubspec.yaml
index 21b1fa04272d..4868f106d648 100644
--- a/packages/firebase_ai/firebase_ai/example/pubspec.yaml
+++ b/packages/firebase_ai/firebase_ai/example/pubspec.yaml
@@ -26,7 +26,7 @@ dependencies:
   flutter:
     sdk: flutter
   flutter_markdown: ^0.6.20
-  just_audio: ^0.9.43
+  flutter_soloud: ^3.1.6
   path_provider: ^2.1.5
   record: ^5.2.1
 
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/.metadata b/packages/firebase_vertexai/firebase_vertexai/example/.metadata
index 784ce1298249..e8f7bf911cbc 100644
--- a/packages/firebase_vertexai/firebase_vertexai/example/.metadata
+++ b/packages/firebase_vertexai/firebase_vertexai/example/.metadata
@@ -4,7 +4,7 @@
 # This file should be version controlled and should not be manually edited.
 
 version:
-  revision: "a14f74ff3a1cbd521163c5f03d68113d50af93d3"
+  revision: "ea121f8859e4b13e47a8f845e4586164519588bc"
   channel: "stable"
 
 project_type: app
@@ -13,11 +13,26 @@ project_type: app
 migration:
   platforms:
     - platform: root
-      create_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
-      base_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
+      create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
+      base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
+    - platform: android
+      create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
+      base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
+    - platform: ios
+      create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
+      base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
+    - platform: linux
+      create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
+      base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
+    - platform: macos
+      create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
+      base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
     - platform: web
-      create_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
-      base_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
+      create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
+      base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
+    - platform: windows
+      create_revision: ea121f8859e4b13e47a8f845e4586164519588bc
+      base_revision: ea121f8859e4b13e47a8f845e4586164519588bc
 
   # User provided section
 
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/.gitignore b/packages/firebase_vertexai/firebase_vertexai/example/android/.gitignore
index 6f568019d3c6..be3943c96d8e 100644
--- a/packages/firebase_vertexai/firebase_vertexai/example/android/.gitignore
+++ b/packages/firebase_vertexai/firebase_vertexai/example/android/.gitignore
@@ -5,9 +5,10 @@ gradle-wrapper.jar
 /gradlew.bat
 /local.properties
 GeneratedPluginRegistrant.java
+.cxx/
 
 # Remember to never publicly share your keystore.
-# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
+# See https://flutter.dev/to/reference-keystore
 key.properties
 **/*.keystore
 **/*.jks
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/app/build.gradle.kts b/packages/firebase_vertexai/firebase_vertexai/example/android/app/build.gradle.kts
new file mode 100644
index 000000000000..3415989fde7e
--- /dev/null
+++ b/packages/firebase_vertexai/firebase_vertexai/example/android/app/build.gradle.kts
@@ -0,0 +1,47 @@
+plugins {
+    id("com.android.application")
+    // START: FlutterFire Configuration
+    id("com.google.gms.google-services")
+    // END: FlutterFire Configuration
+    id("kotlin-android")
+    // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
+    id("dev.flutter.flutter-gradle-plugin")
+}
+
+android {
+    namespace = "com.example.vertex_ai_example"
+    compileSdk = flutter.compileSdkVersion
+    ndkVersion = "27.0.12077973"
+
+    compileOptions {
+        sourceCompatibility = JavaVersion.VERSION_11
+        targetCompatibility = JavaVersion.VERSION_11
+    }
+
+    kotlinOptions {
+        jvmTarget = JavaVersion.VERSION_11.toString()
+    }
+
+    defaultConfig {
+        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+        applicationId = "com.example.vertex_ai_example"
+        // You can update the following values to match your application needs.
+        // For more information, see: https://flutter.dev/to/review-gradle-config.
+        minSdk = 23
+        targetSdk = flutter.targetSdkVersion
+        versionCode = flutter.versionCode
+        versionName = flutter.versionName
+    }
+
+    buildTypes {
+        release {
+            // TODO: Add your own signing config for the release build.
+            // Signing with the debug keys for now, so `flutter run --release` works.
+            signingConfig = signingConfigs.getByName("debug")
+        }
+    }
+}
+
+flutter {
+    source = "../.."
+}
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/debug/AndroidManifest.xml b/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/debug/AndroidManifest.xml
index 399f6981d5d3..d30de11e3410 100644
--- a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/debug/AndroidManifest.xml
+++ b/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/debug/AndroidManifest.xml
@@ -4,4 +4,5 @@
          to allow setting breakpoints, to provide hot reload, etc.
     -->
     <uses-permission android:name="android.permission.INTERNET"/>
+    <application android:usesCleartextTraffic="true" />
 </manifest>
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/AndroidManifest.xml b/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/AndroidManifest.xml
index 3401fcfb42b9..48622205141f 100644
--- a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/AndroidManifest.xml
+++ b/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/AndroidManifest.xml
@@ -1,6 +1,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android">
     <application
-        android:label="example"
+        android:label="vertex_ai_example"
         android:name="${applicationName}"
         android:icon="@mipmap/ic_launcher"
         android:usesCleartextTraffic="true">
@@ -8,6 +8,7 @@
             android:name=".MainActivity"
             android:exported="true"
             android:launchMode="singleTop"
+            android:taskAffinity=""
             android:theme="@style/LaunchTheme"
             android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
             android:hardwareAccelerated="true"
@@ -32,7 +33,7 @@
             android:value="2" />
     </application>
     <!-- Required to query activities that can process text, see:
-         https://developer.android.com/training/package-visibility?hl=en and
+         https://developer.android.com/training/package-visibility and
          https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
 
          In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt b/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt
deleted file mode 100644
index 70f8f08f2479..000000000000
--- a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.example.example
-
-import io.flutter.embedding.android.FlutterActivity
-
-class MainActivity: FlutterActivity()
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/kotlin/com/example/vertex_ai_example/MainActivity.kt b/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/kotlin/com/example/vertex_ai_example/MainActivity.kt
new file mode 100644
index 000000000000..a09c414f7bc6
--- /dev/null
+++ b/packages/firebase_vertexai/firebase_vertexai/example/android/app/src/main/kotlin/com/example/vertex_ai_example/MainActivity.kt
@@ -0,0 +1,5 @@
+package com.example.vertex_ai_example
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity : FlutterActivity()
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/build.gradle.kts b/packages/firebase_vertexai/firebase_vertexai/example/android/build.gradle.kts
new file mode 100644
index 000000000000..89176ef44e8c
--- /dev/null
+++ b/packages/firebase_vertexai/firebase_vertexai/example/android/build.gradle.kts
@@ -0,0 +1,21 @@
+allprojects {
+    repositories {
+        google()
+        mavenCentral()
+    }
+}
+
+val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get()
+rootProject.layout.buildDirectory.value(newBuildDir)
+
+subprojects {
+    val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
+    project.layout.buildDirectory.value(newSubprojectBuildDir)
+}
+subprojects {
+    project.evaluationDependsOn(":app")
+}
+
+tasks.register<Delete>("clean") {
+    delete(rootProject.layout.buildDirectory)
+}
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/gradle.properties b/packages/firebase_vertexai/firebase_vertexai/example/android/gradle.properties
index 598d13fee446..f018a61817f5 100644
--- a/packages/firebase_vertexai/firebase_vertexai/example/android/gradle.properties
+++ b/packages/firebase_vertexai/firebase_vertexai/example/android/gradle.properties
@@ -1,3 +1,3 @@
-org.gradle.jvmargs=-Xmx4G
+org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
 android.useAndroidX=true
 android.enableJetifier=true
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/firebase_vertexai/firebase_vertexai/example/android/gradle/wrapper/gradle-wrapper.properties
index aa49780cd59e..afa1e8eb0a83 100644
--- a/packages/firebase_vertexai/firebase_vertexai/example/android/gradle/wrapper/gradle-wrapper.properties
+++ b/packages/firebase_vertexai/firebase_vertexai/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/android/settings.gradle.kts b/packages/firebase_vertexai/firebase_vertexai/example/android/settings.gradle.kts
new file mode 100644
index 000000000000..9e2d35ccf5e0
--- /dev/null
+++ b/packages/firebase_vertexai/firebase_vertexai/example/android/settings.gradle.kts
@@ -0,0 +1,28 @@
+pluginManagement {
+    val flutterSdkPath = run {
+        val properties = java.util.Properties()
+        file("local.properties").inputStream().use { properties.load(it) }
+        val flutterSdkPath = properties.getProperty("flutter.sdk")
+        require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
+        flutterSdkPath
+    }
+
+    includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
+
+    repositories {
+        google()
+        mavenCentral()
+        gradlePluginPortal()
+    }
+}
+
+plugins {
+    id("dev.flutter.flutter-plugin-loader") version "1.0.0"
+    id("com.android.application") version "8.7.0" apply false
+    // START: FlutterFire Configuration
+    id("com.google.gms.google-services") version("4.3.15") apply false
+    // END: FlutterFire Configuration
+    id("org.jetbrains.kotlin.android") version "1.8.22" apply false
+}
+
+include(":app")
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Podfile b/packages/firebase_vertexai/firebase_vertexai/example/ios/Podfile
index e51a31d9ca9d..2dbf7d728d81 100644
--- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Podfile
+++ b/packages/firebase_vertexai/firebase_vertexai/example/ios/Podfile
@@ -1,5 +1,5 @@
 # Uncomment this line to define a global platform for your project
-# platform :ios, '13.0'
+platform :ios, '13.0'
 
 # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
 ENV['COCOAPODS_DISABLE_STATS'] = 'true'
@@ -29,7 +29,6 @@ flutter_ios_podfile_setup
 
 target 'Runner' do
   use_frameworks!
-  use_modular_headers!
 
   flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
   target 'RunnerTests' do
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/project.pbxproj b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/project.pbxproj
index 98cd0c1ded4a..37f29d6208ac 100644
--- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/project.pbxproj
@@ -7,17 +7,15 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		12DD27C70B6F1A3A29F606CA /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5EC8278BABD88B76D174C9B3 /* Pods_RunnerTests.framework */; };
 		1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
 		331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
-		3414F5B6C6F086F6373F1948 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5F1FA05866A2D0FCA3287B20 /* GoogleService-Info.plist */; };
 		3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
 		74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
-		78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; };
-		901FEC83A38129064032C578 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94CE5BFCDF90764354BB6740 /* Pods_Runner.framework */; };
+		7B483211B8F8447551559CD8 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A7451CAF0BF9B58B1FC94AC /* Pods_Runner.framework */; };
 		97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
 		97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
 		97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
-		B7B3CA2D70F15615E1B8E5D8 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 154D9627A1C14A5ACE0B7B0D /* Pods_RunnerTests.framework */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -46,18 +44,18 @@
 /* Begin PBXFileReference section */
 		1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
 		1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
-		154D9627A1C14A5ACE0B7B0D /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
-		232D95ECCEC6F04B9CEC8925 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
+		1B003FC08370C067F6112BA3 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
+		1E4EFC92E26DC42959308596 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
+		2DF9D5C450661BB71EE1CA4A /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
 		331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
 		331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
 		3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
-		560CA017EC76D8AAE2E21549 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
-		5F1FA05866A2D0FCA3287B20 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = "<group>"; };
+		5A7451CAF0BF9B58B1FC94AC /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		5EC8278BABD88B76D174C9B3 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
 		74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
 		7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
-		8ACDC47C7E9AF1A1B9595598 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
-		94CE5BFCDF90764354BB6740 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		8E74AA7A780E6AD093F2280C /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
 		9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
 		9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
 		97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -65,26 +63,24 @@
 		97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
 		97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
 		97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
-		A85D07EF8959748E1D3E564B /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
-		B0B22A9E291076BD22BA9F10 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
-		E1D0571EA0792087F8F27457 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
+		B2BD865801978D1293EC9548 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
+		B5411DA55636D994211B15CD /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
-		0F5F3CD1ED7DB09B81C92173 /* Frameworks */ = {
+		97C146EB1CF9000F007C117D /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				B7B3CA2D70F15615E1B8E5D8 /* Pods_RunnerTests.framework in Frameworks */,
+				7B483211B8F8447551559CD8 /* Pods_Runner.framework in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		97C146EB1CF9000F007C117D /* Frameworks */ = {
+		E0117E231D8F6E331F0AF95D /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */,
-				901FEC83A38129064032C578 /* Pods_Runner.framework in Frameworks */,
+				12DD27C70B6F1A3A29F606CA /* Pods_RunnerTests.framework in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -99,19 +95,29 @@
 			path = RunnerTests;
 			sourceTree = "<group>";
 		};
-		3C3B3E8596675CC144D1BD5B /* Pods */ = {
+		51AC52FF58548C49E2FD13CA /* Pods */ = {
 			isa = PBXGroup;
 			children = (
-				E1D0571EA0792087F8F27457 /* Pods-Runner.debug.xcconfig */,
-				232D95ECCEC6F04B9CEC8925 /* Pods-Runner.release.xcconfig */,
-				560CA017EC76D8AAE2E21549 /* Pods-Runner.profile.xcconfig */,
-				A85D07EF8959748E1D3E564B /* Pods-RunnerTests.debug.xcconfig */,
-				8ACDC47C7E9AF1A1B9595598 /* Pods-RunnerTests.release.xcconfig */,
-				B0B22A9E291076BD22BA9F10 /* Pods-RunnerTests.profile.xcconfig */,
-			);
+				2DF9D5C450661BB71EE1CA4A /* Pods-Runner.debug.xcconfig */,
+				B2BD865801978D1293EC9548 /* Pods-Runner.release.xcconfig */,
+				1E4EFC92E26DC42959308596 /* Pods-Runner.profile.xcconfig */,
+				1B003FC08370C067F6112BA3 /* Pods-RunnerTests.debug.xcconfig */,
+				8E74AA7A780E6AD093F2280C /* Pods-RunnerTests.release.xcconfig */,
+				B5411DA55636D994211B15CD /* Pods-RunnerTests.profile.xcconfig */,
+			);
+			name = Pods;
 			path = Pods;
 			sourceTree = "<group>";
 		};
+		67A1388587063912C673254D /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				5A7451CAF0BF9B58B1FC94AC /* Pods_Runner.framework */,
+				5EC8278BABD88B76D174C9B3 /* Pods_RunnerTests.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
 		9740EEB11CF90186004384FC /* Flutter */ = {
 			isa = PBXGroup;
 			children = (
@@ -130,9 +136,8 @@
 				97C146F01CF9000F007C117D /* Runner */,
 				97C146EF1CF9000F007C117D /* Products */,
 				331C8082294A63A400263BE5 /* RunnerTests */,
-				5F1FA05866A2D0FCA3287B20 /* GoogleService-Info.plist */,
-				3C3B3E8596675CC144D1BD5B /* Pods */,
-				A50BECFB61A452F592070BAA /* Frameworks */,
+				51AC52FF58548C49E2FD13CA /* Pods */,
+				67A1388587063912C673254D /* Frameworks */,
 			);
 			sourceTree = "<group>";
 		};
@@ -160,15 +165,6 @@
 			path = Runner;
 			sourceTree = "<group>";
 		};
-		A50BECFB61A452F592070BAA /* Frameworks */ = {
-			isa = PBXGroup;
-			children = (
-				94CE5BFCDF90764354BB6740 /* Pods_Runner.framework */,
-				154D9627A1C14A5ACE0B7B0D /* Pods_RunnerTests.framework */,
-			);
-			name = Frameworks;
-			sourceTree = "<group>";
-		};
 /* End PBXGroup section */
 
 /* Begin PBXNativeTarget section */
@@ -176,10 +172,10 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
 			buildPhases = (
-				F5C7CFE0E232B64D613F0623 /* [CP] Check Pods Manifest.lock */,
+				8580F0CE7F25830B9BDEF0A0 /* [CP] Check Pods Manifest.lock */,
 				331C807D294A63A400263BE5 /* Sources */,
 				331C807F294A63A400263BE5 /* Resources */,
-				0F5F3CD1ED7DB09B81C92173 /* Frameworks */,
+				E0117E231D8F6E331F0AF95D /* Frameworks */,
 			);
 			buildRules = (
 			);
@@ -195,23 +191,20 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
 			buildPhases = (
-				F51794D56D63ACA383D5C2E4 /* [CP] Check Pods Manifest.lock */,
+				0C5779354B72E692610FCBAC /* [CP] Check Pods Manifest.lock */,
 				9740EEB61CF901F6004384FC /* Run Script */,
 				97C146EA1CF9000F007C117D /* Sources */,
 				97C146EB1CF9000F007C117D /* Frameworks */,
 				97C146EC1CF9000F007C117D /* Resources */,
 				9705A1C41CF9048500538489 /* Embed Frameworks */,
 				3B06AD1E1E4923F5004D2608 /* Thin Binary */,
-				34F21DFC67109DEAFD936E80 /* [CP] Embed Pods Frameworks */,
+				8F2729CA72CB997339394B4E /* [CP] Embed Pods Frameworks */,
 			);
 			buildRules = (
 			);
 			dependencies = (
 			);
 			name = Runner;
-			packageProductDependencies = (
-				78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */,
-			);
 			productName = Runner;
 			productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
 			productType = "com.apple.product-type.application";
@@ -245,9 +238,6 @@
 				Base,
 			);
 			mainGroup = 97C146E51CF9000F007C117D;
-			packageReferences = (
-				781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */,
-			);
 			productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
 			projectDirPath = "";
 			projectRoot = "";
@@ -274,28 +264,32 @@
 				3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
 				97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
 				97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
-				3414F5B6C6F086F6373F1948 /* GoogleService-Info.plist in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 /* End PBXResourcesBuildPhase section */
 
 /* Begin PBXShellScriptBuildPhase section */
-		34F21DFC67109DEAFD936E80 /* [CP] Embed Pods Frameworks */ = {
+		0C5779354B72E692610FCBAC /* [CP] Check Pods Manifest.lock */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputFileListPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
 			);
-			name = "[CP] Embed Pods Frameworks";
+			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
+			);
+			name = "[CP] Check Pods Manifest.lock";
 			outputFileListPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+			);
+			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
 			showEnvVarsInLog = 0;
 		};
 		3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
@@ -314,64 +308,59 @@
 			shellPath = /bin/sh;
 			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
 		};
-		9740EEB61CF901F6004384FC /* Run Script */ = {
+		8580F0CE7F25830B9BDEF0A0 /* [CP] Check Pods Manifest.lock */ = {
 			isa = PBXShellScriptBuildPhase;
-			alwaysOutOfDate = 1;
 			buildActionMask = 2147483647;
 			files = (
 			);
+			inputFileListPaths = (
+			);
 			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
+			);
+			name = "[CP] Check Pods Manifest.lock";
+			outputFileListPaths = (
 			);
-			name = "Run Script";
 			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+			showEnvVarsInLog = 0;
 		};
-		F51794D56D63ACA383D5C2E4 /* [CP] Check Pods Manifest.lock */ = {
+		8F2729CA72CB997339394B4E /* [CP] Embed Pods Frameworks */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 			);
 			inputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
 			);
-			inputPaths = (
-				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
-				"${PODS_ROOT}/Manifest.lock",
-			);
-			name = "[CP] Check Pods Manifest.lock";
+			name = "[CP] Embed Pods Frameworks";
 			outputFileListPaths = (
-			);
-			outputPaths = (
-				"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
+				"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
-		F5C7CFE0E232B64D613F0623 /* [CP] Check Pods Manifest.lock */ = {
+		9740EEB61CF901F6004384FC /* Run Script */ = {
 			isa = PBXShellScriptBuildPhase;
+			alwaysOutOfDate = 1;
 			buildActionMask = 2147483647;
 			files = (
 			);
-			inputFileListPaths = (
-			);
 			inputPaths = (
-				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
-				"${PODS_ROOT}/Manifest.lock",
-			);
-			name = "[CP] Check Pods Manifest.lock";
-			outputFileListPaths = (
 			);
+			name = "Run Script";
 			outputPaths = (
-				"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
-			showEnvVarsInLog = 0;
+			shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
 		};
 /* End PBXShellScriptBuildPhase section */
 
@@ -466,7 +455,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				SDKROOT = iphoneos;
 				SUPPORTED_PLATFORMS = iphoneos;
@@ -482,14 +471,14 @@
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
 				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
-				DEVELOPMENT_TEAM = YYX2P3XVJ7;
+				DEVELOPMENT_TEAM = S8QB4VV633;
 				ENABLE_BITCODE = NO;
 				INFOPLIST_FILE = Runner/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",
 					"@executable_path/Frameworks",
 				);
-				PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
+				PRODUCT_BUNDLE_IDENTIFIER = com.example.vertexAiExample;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
 				SWIFT_VERSION = 5.0;
@@ -499,14 +488,14 @@
 		};
 		331C8088294A63A400263BE5 /* Debug */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = A85D07EF8959748E1D3E564B /* Pods-RunnerTests.debug.xcconfig */;
+			baseConfigurationReference = 1B003FC08370C067F6112BA3 /* Pods-RunnerTests.debug.xcconfig */;
 			buildSettings = {
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
 				GENERATE_INFOPLIST_FILE = YES;
 				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests;
+				PRODUCT_BUNDLE_IDENTIFIER = com.example.vertexAiExample.RunnerTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -517,14 +506,14 @@
 		};
 		331C8089294A63A400263BE5 /* Release */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = 8ACDC47C7E9AF1A1B9595598 /* Pods-RunnerTests.release.xcconfig */;
+			baseConfigurationReference = 8E74AA7A780E6AD093F2280C /* Pods-RunnerTests.release.xcconfig */;
 			buildSettings = {
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
 				GENERATE_INFOPLIST_FILE = YES;
 				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests;
+				PRODUCT_BUNDLE_IDENTIFIER = com.example.vertexAiExample.RunnerTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_VERSION = 5.0;
 				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@@ -533,14 +522,14 @@
 		};
 		331C808A294A63A400263BE5 /* Profile */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = B0B22A9E291076BD22BA9F10 /* Pods-RunnerTests.profile.xcconfig */;
+			baseConfigurationReference = B5411DA55636D994211B15CD /* Pods-RunnerTests.profile.xcconfig */;
 			buildSettings = {
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
 				GENERATE_INFOPLIST_FILE = YES;
 				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests;
+				PRODUCT_BUNDLE_IDENTIFIER = com.example.vertexAiExample.RunnerTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_VERSION = 5.0;
 				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@@ -596,7 +585,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
 				MTL_ENABLE_DEBUG_INFO = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				SDKROOT = iphoneos;
@@ -647,7 +636,7 @@
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				SDKROOT = iphoneos;
 				SUPPORTED_PLATFORMS = iphoneos;
@@ -665,14 +654,14 @@
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
 				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
-				DEVELOPMENT_TEAM = YYX2P3XVJ7;
+				DEVELOPMENT_TEAM = S8QB4VV633;
 				ENABLE_BITCODE = NO;
 				INFOPLIST_FILE = Runner/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",
 					"@executable_path/Frameworks",
 				);
-				PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
+				PRODUCT_BUNDLE_IDENTIFIER = com.example.vertexAiExample;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -688,14 +677,14 @@
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
 				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
-				DEVELOPMENT_TEAM = YYX2P3XVJ7;
+				DEVELOPMENT_TEAM = S8QB4VV633;
 				ENABLE_BITCODE = NO;
 				INFOPLIST_FILE = Runner/Info.plist;
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",
 					"@executable_path/Frameworks",
 				);
-				PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
+				PRODUCT_BUNDLE_IDENTIFIER = com.example.vertexAiExample;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
 				SWIFT_VERSION = 5.0;
@@ -737,20 +726,6 @@
 			defaultConfigurationName = Release;
 		};
 /* End XCConfigurationList section */
-
-/* Begin XCLocalSwiftPackageReference section */
-		781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = {
-			isa = XCLocalSwiftPackageReference;
-			relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage;
-		};
-/* End XCLocalSwiftPackageReference section */
-
-/* Begin XCSwiftPackageProductDependency section */
-		78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = {
-			isa = XCSwiftPackageProductDependency;
-			productName = FlutterGeneratedPluginSwiftPackage;
-		};
-/* End XCSwiftPackageProductDependency section */
 	};
 	rootObject = 97C146E61CF9000F007C117D /* Project object */;
 }
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index 8178cd1c619c..15cada4838e2 100644
--- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -5,24 +5,6 @@
    <BuildAction
       parallelizeBuildables = "YES"
       buildImplicitDependencies = "YES">
-      <PreActions>
-         <ExecutionAction
-            ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
-            <ActionContent
-               title = "Run Prepare Flutter Framework Script"
-               scriptText = "/bin/sh &quot;$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh&quot; prepare&#10;">
-               <EnvironmentBuildable>
-                  <BuildableReference
-                     BuildableIdentifier = "primary"
-                     BlueprintIdentifier = "97C146ED1CF9000F007C117D"
-                     BuildableName = "Runner.app"
-                     BlueprintName = "Runner"
-                     ReferencedContainer = "container:Runner.xcodeproj">
-                  </BuildableReference>
-               </EnvironmentBuildable>
-            </ActionContent>
-         </ExecutionAction>
-      </PreActions>
       <BuildActionEntries>
          <BuildActionEntry
             buildForTesting = "YES"
@@ -89,12 +71,6 @@
             ReferencedContainer = "container:Runner.xcodeproj">
          </BuildableReference>
       </BuildableProductRunnable>
-      <CommandLineArguments>
-         <CommandLineArgument
-            argument = "-FIRDebugEnabled"
-            isEnabled = "YES">
-         </CommandLineArgument>
-      </CommandLineArguments>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Profile"
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/AppDelegate.swift b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/AppDelegate.swift
index b6363034812b..626664468b89 100644
--- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/AppDelegate.swift
+++ b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/AppDelegate.swift
@@ -1,5 +1,5 @@
-import UIKit
 import Flutter
+import UIKit
 
 @main
 @objc class AppDelegate: FlutterAppDelegate {
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Info.plist b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Info.plist
index a80f00ea0116..ce396f3af000 100644
--- a/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Info.plist
+++ b/packages/firebase_vertexai/firebase_vertexai/example/ios/Runner/Info.plist
@@ -5,7 +5,7 @@
 	<key>CFBundleDevelopmentRegion</key>
 	<string>$(DEVELOPMENT_LANGUAGE)</string>
 	<key>CFBundleDisplayName</key>
-	<string>Example</string>
+	<string>Vertex Ai Example</string>
 	<key>CFBundleExecutable</key>
 	<string>$(EXECUTABLE_NAME)</string>
 	<key>CFBundleIdentifier</key>
@@ -13,7 +13,7 @@
 	<key>CFBundleInfoDictionaryVersion</key>
 	<string>6.0</string>
 	<key>CFBundleName</key>
-	<string>example</string>
+	<string>vertex_ai_example</string>
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
@@ -46,6 +46,6 @@
 	<key>UIApplicationSupportsIndirectInputEvents</key>
 	<true/>
 	<key>NSMicrophoneUsageDescription</key>
-	<string>We need access to the microphone to record audio.</string>
+	<string>Need microphone to talk with Gemini</string>
 </dict>
 </plist>
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/ios/firebase_app_id_file.json b/packages/firebase_vertexai/firebase_vertexai/example/ios/firebase_app_id_file.json
deleted file mode 100644
index 59a23a1a01cc..000000000000
--- a/packages/firebase_vertexai/firebase_vertexai/example/ios/firebase_app_id_file.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "file_generated_by": "FlutterFire CLI",
-  "purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory",
-  "GOOGLE_APP_ID": "1:651313571784:ios:2f1472905da3e8e9b1c2fd",
-  "FIREBASE_PROJECT_ID": "vertex-ai-example-ef5a2",
-  "GCM_SENDER_ID": "651313571784"
-}
\ No newline at end of file
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/bidi_page.dart b/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/bidi_page.dart
index 4cd509d1257f..4d6cd0077c41 100644
--- a/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/bidi_page.dart
+++ b/packages/firebase_vertexai/firebase_vertexai/example/lib/pages/bidi_page.dart
@@ -11,15 +11,15 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
-import 'dart:typed_data';
 import 'dart:async';
-import 'dart:developer';
+import 'dart:developer' as developer;
 
 import 'package:flutter/material.dart';
 import 'package:firebase_vertexai/firebase_vertexai.dart';
+
+import '../utils/audio_input.dart';
+import '../utils/audio_output.dart';
 import '../widgets/message_widget.dart';
-import '../utils/audio_player.dart';
-import '../utils/audio_recorder.dart';
 
 class BidiPage extends StatefulWidget {
   const BidiPage({super.key, required this.title, required this.model});
@@ -48,11 +48,9 @@ class _BidiPageState extends State<BidiPage> {
   bool _recording = false;
   late LiveGenerativeModel _liveModel;
   late LiveSession _session;
-  final _audioManager = AudioStreamManager();
-  final _audioRecorder = InMemoryAudioRecorder();
-  var _chunkBuilder = BytesBuilder();
-  var _audioIndex = 0;
   StreamController<bool> _stopController = StreamController<bool>();
+  final _audioOutput = AudioOutput();
+  final _audioInput = AudioInput();
 
   @override
   void initState() {
@@ -73,6 +71,12 @@ class _BidiPageState extends State<BidiPage> {
         Tool.functionDeclarations([lightControlTool]),
       ],
     );
+    _initAudio();
+  }
+
+  Future<void> _initAudio() async {
+    await _audioOutput.init();
+    await _audioInput.init();
   }
 
   void _scrollDown() {
@@ -90,13 +94,7 @@ class _BidiPageState extends State<BidiPage> {
   @override
   void dispose() {
     if (_sessionOpening) {
-      _audioManager.stopAudioPlayer();
-      _audioManager.disposeAudioPlayer();
-
-      _audioRecorder.stopRecording();
-
       _stopController.close();
-
       _sessionOpening = false;
       _session.close();
     }
@@ -235,7 +233,7 @@ class _BidiPageState extends State<BidiPage> {
       _sessionOpening = true;
       _stopController = StreamController<bool>();
       unawaited(
-        processMessagesContinuously(
+        _processMessagesContinuously(
           stopSignal: _stopController,
         ),
       );
@@ -244,8 +242,6 @@ class _BidiPageState extends State<BidiPage> {
       await _stopController.close();
 
       await _session.close();
-      await _audioManager.stopAudioPlayer();
-      await _audioManager.disposeAudioPlayer();
       _sessionOpening = false;
     }
 
@@ -259,21 +255,25 @@ class _BidiPageState extends State<BidiPage> {
       _recording = true;
     });
     try {
-      await _audioRecorder.checkPermission();
-      final audioRecordStream = _audioRecorder.startRecordingStream();
+      var inputStream = await _audioInput.startRecordingStream();
+      await _audioOutput.playStream();
       // Map the Uint8List stream to InlineDataPart stream
-      final mediaChunkStream = audioRecordStream.map((data) {
-        return InlineDataPart('audio/pcm', data);
-      });
-      await _session.sendMediaStream(mediaChunkStream);
+      if (inputStream != null) {
+        final inlineDataStream = inputStream.map((data) {
+          return InlineDataPart('audio/pcm', data);
+        });
+
+        await _session.sendMediaStream(inlineDataStream);
+      }
     } catch (e) {
+      developer.log(e.toString());
       _showError(e.toString());
     }
   }
 
   Future<void> _stopRecording() async {
     try {
-      await _audioRecorder.stopRecording();
+      await _audioInput.stopRecording();
     } catch (e) {
       _showError(e.toString());
     }
@@ -299,7 +299,7 @@ class _BidiPageState extends State<BidiPage> {
     });
   }
 
-  Future<void> processMessagesContinuously({
+  Future<void> _processMessagesContinuously({
     required StreamController<bool> stopSignal,
   }) async {
     bool shouldContinue = true;
@@ -336,11 +336,8 @@ class _BidiPageState extends State<BidiPage> {
       if (message.modelTurn != null) {
         await _handleLiveServerContent(message);
       }
-      if (message.turnComplete != null && message.turnComplete!) {
-        await _handleTurnComplete();
-      }
       if (message.interrupted != null && message.interrupted!) {
-        log('Interrupted: $response');
+        developer.log('Interrupted: $response');
       }
     } else if (message is LiveServerToolCall && message.functionCalls != null) {
       await _handleLiveServerToolCall(message);
@@ -356,7 +353,7 @@ class _BidiPageState extends State<BidiPage> {
         } else if (part is InlineDataPart) {
           await _handleInlineDataPart(part);
         } else {
-          log('receive part with type ${part.runtimeType}');
+          developer.log('receive part with type ${part.runtimeType}');
         }
       }
     }
@@ -377,29 +374,7 @@ class _BidiPageState extends State<BidiPage> {
 
   Future<void> _handleInlineDataPart(InlineDataPart part) async {
     if (part.mimeType.startsWith('audio')) {
-      _chunkBuilder.add(part.bytes);
-      _audioIndex++;
-      if (_audioIndex == 15) {
-        Uint8List chunk = await audioChunkWithHeader(
-          _chunkBuilder.toBytes(),
-          24000,
-        );
-        _audioManager.addAudio(chunk);
-        _chunkBuilder.clear();
-        _audioIndex = 0;
-      }
-    }
-  }
-
-  Future<void> _handleTurnComplete() async {
-    if (_chunkBuilder.isNotEmpty) {
-      Uint8List chunk = await audioChunkWithHeader(
-        _chunkBuilder.toBytes(),
-        24000,
-      );
-      _audioManager.addAudio(chunk);
-      _audioIndex = 0;
-      _chunkBuilder.clear();
+      _audioOutput.addAudioStream(part.bytes);
     }
   }
 
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/lib/utils/audio_input.dart b/packages/firebase_vertexai/firebase_vertexai/example/lib/utils/audio_input.dart
new file mode 100644
index 000000000000..869d4ee32781
--- /dev/null
+++ b/packages/firebase_vertexai/firebase_vertexai/example/lib/utils/audio_input.dart
@@ -0,0 +1,95 @@
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'package:flutter/material.dart';
+import 'package:record/record.dart';
+import 'dart:typed_data';
+
+class AudioInput extends ChangeNotifier {
+  final _recorder = AudioRecorder();
+  final AudioEncoder _encoder = AudioEncoder.pcm16bits;
+  bool isRecording = false;
+  bool isPaused = false;
+  Stream<Uint8List>? audioStream;
+
+  Future<void> init() async {
+    await _checkPermission();
+  }
+
+  @override
+  void dispose() {
+    _recorder.dispose();
+    super.dispose();
+  }
+
+  Future<void> _checkPermission() async {
+    final hasPermission = await _recorder.hasPermission();
+    if (!hasPermission) {
+      throw MicrophonePermissionDeniedException(
+        'App does not have mic permissions',
+      );
+    }
+  }
+
+  Future<Stream<Uint8List>?> startRecordingStream() async {
+    var recordConfig = RecordConfig(
+      encoder: _encoder,
+      sampleRate: 24000,
+      numChannels: 1,
+      echoCancel: true,
+      noiseSuppress: true,
+      androidConfig: const AndroidRecordConfig(
+        audioSource: AndroidAudioSource.voiceCommunication,
+      ),
+      iosConfig: const IosRecordConfig(categoryOptions: []),
+    );
+    await _recorder.listInputDevices();
+    audioStream = await _recorder.startStream(recordConfig);
+    isRecording = true;
+    notifyListeners();
+    return audioStream;
+  }
+
+  Future<void> stopRecording() async {
+    await _recorder.stop();
+    isRecording = false;
+    notifyListeners();
+  }
+
+  Future<void> togglePause() async {
+    if (isPaused) {
+      await _recorder.resume();
+      isPaused = false;
+    } else {
+      await _recorder.pause();
+      isPaused = true;
+    }
+    notifyListeners();
+    return;
+  }
+}
+
+/// An exception thrown when microphone permission is denied or not granted.
+class MicrophonePermissionDeniedException implements Exception {
+  /// The optional message associated with the permission denial.
+  final String? message;
+
+  /// Creates a new [MicrophonePermissionDeniedException] with an optional [message].
+  MicrophonePermissionDeniedException([this.message]);
+
+  @override
+  String toString() {
+    return 'MicrophonePermissionDeniedException: $message';
+  }
+}
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/lib/utils/audio_output.dart b/packages/firebase_vertexai/firebase_vertexai/example/lib/utils/audio_output.dart
new file mode 100644
index 000000000000..b97ad3478f5b
--- /dev/null
+++ b/packages/firebase_vertexai/firebase_vertexai/example/lib/utils/audio_output.dart
@@ -0,0 +1,66 @@
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import 'dart:typed_data';
+
+import 'package:flutter_soloud/flutter_soloud.dart';
+
+class AudioOutput {
+  AudioSource? stream;
+  SoundHandle? handle;
+
+  Future<void> init() async {
+    // Initialize the player.
+    await SoLoud.instance.init(sampleRate: 24000, channels: Channels.mono);
+    await setupNewStream();
+  }
+
+  Future<void> setupNewStream() async {
+    if (SoLoud.instance.isInitialized) {
+      // Stop and clear any previous playback handle if it's still valid
+      await stopStream(); // Ensure previous sound is stopped
+
+      stream = SoLoud.instance.setBufferStream(
+        maxBufferSizeBytes:
+            1024 * 1024 * 10, // 10MB of max buffer (not allocated)
+        bufferingType: BufferingType.released,
+        bufferingTimeNeeds: 0,
+        onBuffering: (isBuffering, handle, time) {},
+      );
+      // Reset handle to null until the stream is played again
+      handle = null;
+    }
+  }
+
+  Future<AudioSource?> playStream() async {
+    handle = await SoLoud.instance.play(stream!);
+    return stream;
+  }
+
+  Future<void> stopStream() async {
+    if (stream != null &&
+        handle != null &&
+        SoLoud.instance.getIsValidVoiceHandle(handle!)) {
+      SoLoud.instance.setDataIsEnded(stream!);
+      await SoLoud.instance.stop(handle!);
+
+      // Clear old stream, set up new session for next time.
+      await setupNewStream();
+    }
+  }
+
+  void addAudioStream(Uint8List audioChunk) {
+    SoLoud.instance.addAudioDataStream(stream!, audioChunk);
+  }
+}
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/lib/utils/audio_player.dart b/packages/firebase_vertexai/firebase_vertexai/example/lib/utils/audio_player.dart
deleted file mode 100644
index 3c5559481ed7..000000000000
--- a/packages/firebase_vertexai/firebase_vertexai/example/lib/utils/audio_player.dart
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2025 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import 'dart:typed_data';
-import 'dart:async';
-
-import 'package:just_audio/just_audio.dart';
-
-/// Creates a WAV audio chunk with a properly formatted header.
-Future<Uint8List> audioChunkWithHeader(
-  List<int> data,
-  int sampleRate,
-) async {
-  var channels = 1;
-
-  int byteRate = ((16 * sampleRate * channels) / 8).round();
-
-  var size = data.length;
-  var fileSize = size + 36;
-
-  Uint8List header = Uint8List.fromList([
-    // "RIFF"
-    82, 73, 70, 70,
-    fileSize & 0xff,
-    (fileSize >> 8) & 0xff,
-    (fileSize >> 16) & 0xff,
-    (fileSize >> 24) & 0xff,
-    // WAVE
-    87, 65, 86, 69,
-    // fmt
-    102, 109, 116, 32,
-    // fmt chunk size 16
-    16, 0, 0, 0,
-    // Type of format
-    1, 0,
-    // One channel
-    channels, 0,
-    // Sample rate
-    sampleRate & 0xff,
-    (sampleRate >> 8) & 0xff,
-    (sampleRate >> 16) & 0xff,
-    (sampleRate >> 24) & 0xff,
-    // Byte rate
-    byteRate & 0xff,
-    (byteRate >> 8) & 0xff,
-    (byteRate >> 16) & 0xff,
-    (byteRate >> 24) & 0xff,
-    // Uhm
-    ((16 * channels) / 8).round(), 0,
-    // bitsize
-    16, 0,
-    // "data"
-    100, 97, 116, 97,
-    size & 0xff,
-    (size >> 8) & 0xff,
-    (size >> 16) & 0xff,
-    (size >> 24) & 0xff,
-    // incoming data
-    ...data,
-  ]);
-  return header;
-}
-
-class ByteStreamAudioSource extends StreamAudioSource {
-  ByteStreamAudioSource(this.bytes) : super(tag: 'Byte Stream Audio');
-
-  final Uint8List bytes;
-
-  @override
-  Future<StreamAudioResponse> request([int? start, int? end]) async {
-    start ??= 0;
-    end ??= bytes.length;
-    return StreamAudioResponse(
-      sourceLength: bytes.length,
-      contentLength: end - start,
-      offset: start,
-      stream: Stream.value(bytes.sublist(start, end)),
-      contentType: 'audio/wav', // Or the appropriate content type
-    );
-  }
-}
-
-class AudioStreamManager {
-  final _audioPlayer = AudioPlayer();
-  final _audioChunkController = StreamController<Uint8List>();
-  var _audioSource = ConcatenatingAudioSource(
-    children: [],
-  );
-
-  AudioStreamManager() {
-    _initAudioPlayer();
-  }
-
-  Future<void> _initAudioPlayer() async {
-    // 1. Create a ConcatenatingAudioSource to handle the stream
-    await _audioPlayer.setAudioSource(_audioSource);
-
-    // 2. Listen to the stream of audio chunks
-    _audioChunkController.stream.listen(_addAudioChunk);
-
-    await _audioPlayer.play(); // Start playing (even if initially empty)
-
-    _audioPlayer.processingStateStream.listen((state) async {
-      if (state == ProcessingState.completed) {
-        await _audioPlayer
-            .pause(); // Or player.stop() if you want to release resources
-        await _audioPlayer.seek(Duration.zero, index: 0);
-        await _audioSource.clear();
-        await _audioPlayer.play();
-      }
-    });
-  }
-
-  Future<void> _addAudioChunk(Uint8List chunk) async {
-    var buffer = ByteStreamAudioSource(chunk);
-
-    await _audioSource.add(buffer);
-  }
-
-  void addAudio(Uint8List chunk) {
-    _audioChunkController.add(chunk);
-  }
-
-  Future<void> stopAudioPlayer() async {
-    await _audioPlayer.stop();
-  }
-
-  Future<void> disposeAudioPlayer() async {
-    await _audioPlayer.dispose();
-    await _audioChunkController.close();
-  }
-}
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/lib/utils/audio_recorder.dart b/packages/firebase_vertexai/firebase_vertexai/example/lib/utils/audio_recorder.dart
deleted file mode 100644
index 1f3710cd0c8f..000000000000
--- a/packages/firebase_vertexai/firebase_vertexai/example/lib/utils/audio_recorder.dart
+++ /dev/null
@@ -1,245 +0,0 @@
-// Copyright 2025 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-import 'dart:async';
-import 'dart:io';
-import 'dart:typed_data';
-
-import 'package:flutter/material.dart';
-import 'package:path_provider/path_provider.dart';
-import 'package:record/record.dart';
-
-/// An exception thrown when microphone permission is denied or not granted.
-class MicrophonePermissionDeniedException implements Exception {
-  /// The optional message associated with the permission denial.
-  final String? message;
-
-  /// Creates a new [MicrophonePermissionDeniedException] with an optional [message].
-  MicrophonePermissionDeniedException([this.message]);
-
-  @override
-  String toString() {
-    if (message == null) {
-      return 'MicrophonePermissionDeniedException';
-    }
-    return 'MicrophonePermissionDeniedException: $message';
-  }
-}
-
-class Resampler {
-  /// Resamples 16-bit integer PCM audio data from a source sample rate to a
-  /// target sample rate using linear interpolation.
-  ///
-  /// [sourceRate]: The sample rate of the input audio data.
-  /// [targetRate]: The desired sample rate of the output audio data.
-  /// [input]: The input audio data as a Uint8List containing 16-bit PCM samples.
-  ///
-  /// Returns a new Uint8List containing 16-bit PCM samples resampled to the
-  /// target rate.
-  static Uint8List resampleLinear16(
-    int sourceRate,
-    int targetRate,
-    Uint8List input,
-  ) {
-    if (sourceRate == targetRate) return input; // No resampling needed
-
-    final outputLength = (input.length * targetRate / sourceRate).round();
-    final output = Uint8List(outputLength);
-    final inputData = Int16List.view(input.buffer);
-    final outputData = Int16List.view(output.buffer);
-
-    for (int i = 0; i < outputLength ~/ 2; i++) {
-      final sourcePosition = i * sourceRate / targetRate;
-      final index1 = sourcePosition.floor();
-      final index2 = index1 + 1;
-      final weight2 = sourcePosition - index1;
-      final weight1 = 1.0 - weight2;
-
-      // Ensure indices are within the valid range
-      final sample1 = inputData[index1.clamp(0, inputData.length - 1)];
-      final sample2 = inputData[index2.clamp(0, inputData.length - 1)];
-
-      // Interpolate and convert back to 16-bit integer
-      final interpolatedSample =
-          (sample1 * weight1 + sample2 * weight2).toInt();
-
-      outputData[i] = interpolatedSample;
-    }
-
-    return output;
-  }
-}
-
-class InMemoryAudioRecorder {
-  final _audioChunks = <Uint8List>[];
-  final _recorder = AudioRecorder();
-  StreamSubscription<Uint8List>? _recordSubscription;
-  late String? _lastAudioPath;
-  AudioEncoder _encoder = AudioEncoder.pcm16bits;
-
-  Future<String> _getPath() async {
-    String suffix;
-    if (_encoder == AudioEncoder.pcm16bits) {
-      suffix = 'pcm';
-    } else if (_encoder == AudioEncoder.aacLc) {
-      suffix = 'm4a';
-    } else {
-      suffix = 'wav';
-    }
-    final dir = await getDownloadsDirectory();
-    final path =
-        '${dir!.path}/audio_${DateTime.now().millisecondsSinceEpoch}.$suffix';
-    return path;
-  }
-
-  Future<void> checkPermission() async {
-    final hasPermission = await _recorder.hasPermission();
-    if (!hasPermission) {
-      throw MicrophonePermissionDeniedException('Not having mic permission');
-    }
-  }
-
-  Future<bool> _isEncoderSupported(AudioEncoder encoder) async {
-    final isSupported = await _recorder.isEncoderSupported(
-      encoder,
-    );
-
-    if (!isSupported) {
-      debugPrint('${encoder.name} is not supported on this platform.');
-      debugPrint('Supported encoders are:');
-
-      for (final e in AudioEncoder.values) {
-        if (await _recorder.isEncoderSupported(e)) {
-          debugPrint('- ${e.name}');
-        }
-      }
-    }
-
-    return isSupported;
-  }
-
-  Future<void> startRecording({bool fromFile = false}) async {
-    if (!await _isEncoderSupported(_encoder)) {
-      return;
-    }
-    var recordConfig = RecordConfig(
-      encoder: _encoder,
-      sampleRate: 16000,
-      numChannels: 1,
-      androidConfig: const AndroidRecordConfig(
-        muteAudio: true,
-        audioSource: AndroidAudioSource.mic,
-      ),
-    );
-    final devs = await _recorder.listInputDevices();
-    debugPrint(devs.toString());
-    _lastAudioPath = await _getPath();
-    if (fromFile) {
-      await _recorder.start(recordConfig, path: _lastAudioPath!);
-    } else {
-      final stream = await _recorder.startStream(recordConfig);
-      _recordSubscription = stream.listen(_audioChunks.add);
-    }
-  }
-
-  Future<void> startRecordingFile() async {
-    if (!await _isEncoderSupported(_encoder)) {
-      return;
-    }
-    var recordConfig = RecordConfig(
-      encoder: _encoder,
-      sampleRate: 16000,
-      numChannels: 1,
-    );
-    final devs = await _recorder.listInputDevices();
-    debugPrint(devs.toString());
-    _lastAudioPath = await _getPath();
-    await _recorder.start(recordConfig, path: _lastAudioPath!);
-  }
-
-  Stream<Uint8List> startRecordingStream() async* {
-    if (!await _isEncoderSupported(_encoder)) {
-      return;
-    }
-    var recordConfig = RecordConfig(
-      encoder: _encoder,
-      sampleRate: 16000,
-      numChannels: 1,
-    );
-    final devices = await _recorder.listInputDevices();
-    debugPrint(devices.toString());
-    final stream = await _recorder.startStream(recordConfig);
-
-    await for (final data in stream) {
-      yield data;
-    }
-  }
-
-  Future<void> stopRecording() async {
-    await _recordSubscription?.cancel();
-    _recordSubscription = null;
-
-    await _recorder.stop();
-  }
-
-  Future<Uint8List> fetchAudioBytes({
-    bool fromFile = false,
-    bool removeHeader = false,
-  }) async {
-    Uint8List resultBytes;
-    if (fromFile) {
-      resultBytes = await _getAudioBytesFromFile(_lastAudioPath!);
-    } else {
-      final builder = BytesBuilder();
-      _audioChunks.forEach(builder.add);
-      resultBytes = builder.toBytes();
-    }
-
-    // resample
-    resultBytes = Resampler.resampleLinear16(44100, 16000, resultBytes);
-    final dir = await getDownloadsDirectory();
-    final path = '${dir!.path}/audio_resampled.pcm';
-    final file = File(path);
-    final sink = file.openWrite();
-
-    sink.add(resultBytes);
-
-    await sink.close();
-    return resultBytes;
-  }
-
-  Future<Uint8List> _removeWavHeader(Uint8List audio) async {
-    // Assuming a standard WAV header size of 44 bytes
-    const wavHeaderSize = 44;
-    final audioData = audio.sublist(wavHeaderSize);
-    return audioData;
-  }
-
-  Future<Uint8List> _getAudioBytesFromFile(
-    String filePath, {
-    bool removeHeader = false,
-  }) async {
-    final file = File(_lastAudioPath!);
-
-    if (!file.existsSync()) {
-      throw Exception('Audio file not found: ${file.path}');
-    }
-
-    var pcmBytes = await file.readAsBytes();
-    if (removeHeader) {
-      pcmBytes = await _removeWavHeader(pcmBytes);
-    }
-    return pcmBytes;
-  }
-}
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner.xcodeproj/project.pbxproj b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner.xcodeproj/project.pbxproj
index 4bc66a519ca5..47f1397e22f9 100644
--- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner.xcodeproj/project.pbxproj
+++ b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner.xcodeproj/project.pbxproj
@@ -198,7 +198,6 @@
 				587C61AFC0E2B0BF5340F8E8 /* Pods-RunnerTests.release.xcconfig */,
 				5C2B5E4F1CE100E1FA5D9DC5 /* Pods-RunnerTests.profile.xcconfig */,
 			);
-			name = Pods;
 			path = Pods;
 			sourceTree = "<group>";
 		};
@@ -584,6 +583,7 @@
 					"@executable_path/../Frameworks",
 				);
 				PROVISIONING_PROFILE_SPECIFIER = "";
+				STRIP_STYLE = "non-global";
 				SWIFT_VERSION = 5.0;
 			};
 			name = Profile;
@@ -716,6 +716,7 @@
 					"@executable_path/../Frameworks",
 				);
 				PROVISIONING_PROFILE_SPECIFIER = "";
+				STRIP_STYLE = "non-global";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 				SWIFT_VERSION = 5.0;
 			};
@@ -736,6 +737,7 @@
 					"@executable_path/../Frameworks",
 				);
 				PROVISIONING_PROFILE_SPECIFIER = "";
+				STRIP_STYLE = "non-global";
 				SWIFT_VERSION = 5.0;
 			};
 			name = Release;
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/DebugProfile.entitlements b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/DebugProfile.entitlements
index b4bd9ee174a1..d3eb4e3f2a11 100644
--- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/DebugProfile.entitlements
+++ b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/DebugProfile.entitlements
@@ -14,5 +14,7 @@
 	<true/>
   <key>com.apple.security.device.audio-input</key>
   <true/>
+  <key>com.apple.security.network.client</key>
+<true/>
 </dict>
 </plist>
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Release.entitlements b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Release.entitlements
index 2f9659c917fb..f18debee72ff 100644
--- a/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Release.entitlements
+++ b/packages/firebase_vertexai/firebase_vertexai/example/macos/Runner/Release.entitlements
@@ -6,5 +6,7 @@
 	<true/>
 	<key>com.apple.security.files.downloads.read-write</key>
 	<true/>
+  <key>com.apple.security.network.client</key>
+<true/>
 </dict>
 </plist>
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/pubspec.yaml b/packages/firebase_vertexai/firebase_vertexai/example/pubspec.yaml
index a043982716f2..7f62a9dd4a3b 100644
--- a/packages/firebase_vertexai/firebase_vertexai/example/pubspec.yaml
+++ b/packages/firebase_vertexai/firebase_vertexai/example/pubspec.yaml
@@ -26,7 +26,7 @@ dependencies:
   flutter:
     sdk: flutter
   flutter_markdown: ^0.6.20
-  just_audio: ^0.9.43
+  flutter_soloud: ^3.1.6
   path_provider: ^2.1.5
   record: ^5.2.1
 
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/web/index.html b/packages/firebase_vertexai/firebase_vertexai/example/web/index.html
index adc47a626031..dcd929827260 100644
--- a/packages/firebase_vertexai/firebase_vertexai/example/web/index.html
+++ b/packages/firebase_vertexai/firebase_vertexai/example/web/index.html
@@ -1,5 +1,6 @@
 <!DOCTYPE html>
 <html>
+
 <head>
   <!--
     If you are serving your web app in a path other than the root, change the
@@ -27,12 +28,16 @@
   <link rel="apple-touch-icon" href="icons/Icon-192.png">
 
   <!-- Favicon -->
-  <link rel="icon" type="image/png" href="favicon.png"/>
+  <link rel="icon" type="image/png" href="favicon.png" />
 
   <title>flutterfire_vertexai</title>
   <link rel="manifest" href="manifest.json">
 </head>
+
 <body>
   <script src="flutter_bootstrap.js" async></script>
+  <script src="assets/packages/flutter_soloud/web/libflutter_soloud_plugin.js" defer></script>
+  <script src="assets/packages/flutter_soloud/web/init_module.dart.js" defer></script>
 </body>
-</html>
+
+</html>
\ No newline at end of file
diff --git a/packages/firebase_vertexai/firebase_vertexai/example/windows/.gitignore b/packages/firebase_vertexai/firebase_vertexai/example/windows/.gitignore
new file mode 100644
index 000000000000..d492d0d98c8f
--- /dev/null
+++ b/packages/firebase_vertexai/firebase_vertexai/example/windows/.gitignore
@@ -0,0 +1,17 @@
+flutter/ephemeral/
+
+# Visual Studio user-specific files.
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# Visual Studio build-related files.
+x64/
+x86/
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/