using Android.Bluetooth; using Android.Content; using Android.OS; using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Maui.Controls; namespace NotVPR_Remote; public partial class MainPage : ContentPage { BluetoothAdapter _adapter; IList _pairedDevices; BluetoothSocket _socket; Stream _outputStream; Stream _inputStream; CancellationTokenSource _receiveCts; long lastTimeSent = 300; public MainPage() { InitializeComponent(); _adapter = BluetoothAdapter.DefaultAdapter; if (_adapter == null || !_adapter.IsEnabled) { DisplayAlert("Bluetooth Error", "Bluetooth is disabled or not available on this device.", "OK"); return; } LoadPairedDevices(); } void LoadPairedDevices() { DevicePicker.Items.Clear(); _pairedDevices = new List(); var paired = _adapter.BondedDevices; foreach (var device in paired) { _pairedDevices.Add(device); DevicePicker.Items.Add(device.Name); } if (_pairedDevices.Count > 0) DevicePicker.SelectedIndex = 0; else DevicePicker.Title = "No paired devices found"; } async void OnConnectClicked(object sender, EventArgs e) { if (DevicePicker.SelectedIndex == -1) { await DisplayAlert("Error", "Select a device first", "OK"); return; } var device = _pairedDevices[DevicePicker.SelectedIndex]; var sppUuid = Java.Util.UUID.FromString("00001101-0000-1000-8000-00805F9B34FB"); try { _socket?.Close(); _socket = device.CreateRfcommSocketToServiceRecord(sppUuid); await Task.Run(() => _socket.Connect()); _outputStream = _socket.OutputStream; _inputStream = _socket.InputStream; _receiveCts = new CancellationTokenSource(); StartListeningForMessages(_receiveCts.Token); if (_socket.IsConnected) { var stream = _socket.OutputStream; var data = Encoding.UTF8.GetBytes("Hello\n"); await stream.WriteAsync(data, 0, data.Length); await stream.FlushAsync(); } StatusLabel.Text = $"Connected to {device.Name}"; } catch (Exception ex) { await DisplayAlert("Connection Error", ex.Message, "OK"); StatusLabel.Text = "Connection failed"; } } async void OnButtonClicked(object sender, EventArgs e) { if (_socket == null || !_socket.IsConnected || _outputStream == null) { await DisplayAlert("Error", "Not connected to any device.", "OK"); return; } var button = (Button)sender; string message = button.Text switch { "↑" => "NAV_UP", "↓" => "NAV_DOWN", "←" => "NAV_LEFT", "→" => "NAV_RIGHT", "⇚" => "-EP", "⇛" => "+EP", "●" => "SPACE", "Home" => "HOME", "Mute" => "MUTE", "Vol -" => "VOLUME_DOWN", "Vol +" => "VOLUME_UP", _ => "UNKNOWN" }; try { byte[] data = Encoding.UTF8.GetBytes(message + "\n"); await _outputStream.WriteAsync(data, 0, data.Length); } catch (Exception ex) { await DisplayAlert("Send Error", ex.Message, "OK"); } } private void PlaybackSlider_ValueChanged(object sender, ValueChangedEventArgs e) { PlaybackProgress.Progress = PlaybackSlider.Value; string message = "Time:" + PlaybackSlider.Value.ToString(); try { if (lastTimeSent < PlaybackSlider.Value + 2 || lastTimeSent > PlaybackSlider.Value - 2) { byte[] data = Encoding.UTF8.GetBytes(message + "\n"); _outputStream.WriteAsync(data, 0, data.Length); lastTimeSent = (long)PlaybackSlider.Value; } } catch (Exception ex) { Console.WriteLine($"Slider Send Error: {ex.Message}"); } } void StartListeningForMessages(CancellationToken token) { Task.Run(async () => { byte[] buffer = new byte[1024]; try { while (!token.IsCancellationRequested) { int bytesRead = await _inputStream.ReadAsync(buffer, 0, buffer.Length, token); if (bytesRead > 0) { string receivedMessage = Encoding.UTF8.GetString(buffer, 0, bytesRead); Console.WriteLine($"Received: {receivedMessage}"); MainThread.BeginInvokeOnMainThread(() => { StatusLabel.Text = $"Received: {receivedMessage}"; // TODO: Handle message as needed }); } } } catch (Exception ex) { Console.WriteLine($"Receive error: {ex.Message}"); } }, token); } protected override void OnDisappearing() { base.OnDisappearing(); _receiveCts?.Cancel(); _inputStream?.Close(); _outputStream?.Close(); _socket?.Close(); } void OnDisconnectClicked(object sender, EventArgs e) { _receiveCts?.Cancel(); _inputStream?.Close(); _outputStream?.Close(); _socket?.Close(); StatusLabel.Text = "Disconnected"; } }