208 lines
5.8 KiB
C#
208 lines
5.8 KiB
C#
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<BluetoothDevice> _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<BluetoothDevice>();
|
|
|
|
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";
|
|
}
|
|
}
|