| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 | using Android.Bluetooth;using Android.Bluetooth.LE;using Android.Content;using InABox.Core;using Microsoft.Maui.ApplicationModel;namespace InABox.Avalonia.Platform.Android;public class Android_Bluetooth : IBluetooth{    public Logger? Logger { get; set; }    public CoreObservableCollection<IBluetoothDevice> Devices { get; private set; } = new CoreObservableCollection<IBluetoothDevice>();        private readonly BluetoothLeScanner? _scanner;    public event EventHandler? Changed;    public Android_Bluetooth()    {        var _manager = Application.Context.GetSystemService(Context.BluetoothService) as BluetoothManager;        var _adapter = _manager?.Adapter;        _scanner = _adapter?.BluetoothLeScanner;                Task.Run(() =>        {            while (true)            {                var stale = Devices.ToArray().Where(x => (x == null) || (x.LastSeen < DateTime.Now.Subtract(new TimeSpan(0, 0, 5))))                    .ToArray();                if (stale.Any())                {                    Devices.RemoveRange(stale);                    Changed?.Invoke(this, EventArgs.Empty);                }                                    Task.Delay(500);            }        });    }        public static async Task<bool> IsPermitted<TPermission>() where TPermission : Permissions.BasePermission, new()    {        try        {            PermissionStatus status = await Permissions.CheckStatusAsync<TPermission>();            if (status == PermissionStatus.Granted)                return true;            var request = await Permissions.RequestAsync<TPermission>();            return request == PermissionStatus.Granted;        }        catch (TaskCanceledException ex)        {            return false;        }    }    public async Task<bool> IsAvailable()    {        if (await IsPermitted<Permissions.Bluetooth>())             return _scanner != null;        return false;    }    BluetoothScanManager? _callback;        public async Task<bool> StartScanningAsync(Guid configServiceId)    {        if (await IsAvailable())        {            _callback = new BluetoothScanManager((d) => DoDeviceFound(d, configServiceId), ScanStopped);            _scanner!.StartScan(_callback);            return true;        }        return false;    }    public async Task<bool> StopScanningAsync()    {        if (await IsAvailable())        {            if (_callback != null)            {                _scanner!.StopScan(_callback);                return true;            }        }        return false;    }        private void DoDeviceFound(ScanResult device, Guid configServiceId)    {        var isTarget = device.ScanRecord?.ServiceUuids?            .Any(x=>string.Equals(x.ToString(),configServiceId.ToString(), StringComparison.OrdinalIgnoreCase))                        ?? false;        if (isTarget)        {            var abd = Devices.FirstOrDefault(x => x.ID == device.Device?.Address);            if (abd == null)            {                if (isTarget)                {                    var services = device.ScanRecord?.ServiceUuids?                        .Select(x => Guid.Parse(x.ToString()))                        .Where(x => !x.ToString().ToUpper().EndsWith("-0000-1000-8000-00805F9B34FB") &&                                    configServiceId != x)                        .ToArray() ?? [];                    if (services.Any())                    {                        abd = new Android_BluetoothDevice(device, services, DateTime.Now);                        Devices.Add(abd);                        Changed?.Invoke(this, EventArgs.Empty);                    }                }            }            else                abd.LastSeen = DateTime.Now;        }    }    private void ScanStopped()    {        _callback = null;    }    public async Task<IConnectedBluetoothDevice?> Connect(IBluetoothDevice device)    {        if (device is Android_BluetoothDevice d && d.Scan.Device is BluetoothDevice bd)        {            var result = new Android_ConnectedBluetoothDevice(bd);            if (await result.ConnectAsync())            {                await result.DiscoverServicesAsync();                return result;            }        }        return null;    }                public async Task<bool> Disconnect(IConnectedBluetoothDevice device)    {        if (device is Android_ConnectedBluetoothDevice d)            d.Dispose();                return await Task.FromResult(true);    }}
 |