Files
Peter Freeman Foot d7d5b7b3fe .NET 6.0 MAUI support
2022-05-24 13:36:25 +01:00

225 lines
5.9 KiB
C#

// 32feet.NET - Personal Area Networking for .NET
//
// InTheHand.Net.Bluetooth.BluetoothClient (Android)
//
// Copyright (c) 2018-2022 In The Hand Ltd, All rights reserved.
// This source code is licensed under the MIT License
using Android.Bluetooth;
using Android.Content;
using Android.OS;
using InTheHand.Net.Bluetooth;
using InTheHand.Net.Bluetooth.Droid;
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Threading;
#if NET6_0_OR_GREATER
using Microsoft.Maui.ApplicationModel;
#else
using Xamarin.Essentials;
#endif
namespace InTheHand.Net.Sockets
{
partial class BluetoothClient
{
private BluetoothSocket _socket;
private BluetoothRadio _radio;
private void PlatformInitialize()
{
_radio = BluetoothRadio.Default;
if (_radio != null && _radio.Mode == RadioMode.PowerOff)
_radio.Mode = RadioMode.Connectable;
}
IEnumerable<BluetoothDeviceInfo> GetPairedDevices()
{
foreach(BluetoothDevice device in ((BluetoothAdapter)_radio).BondedDevices)
{
yield return device;
}
yield break;
}
IReadOnlyCollection<BluetoothDeviceInfo> PlatformDiscoverDevices(int maxDevices)
{
List<BluetoothDeviceInfo> devices = new List<BluetoothDeviceInfo>();
HandlerThread handlerThread = new HandlerThread("ht");
handlerThread.Start();
Looper looper = handlerThread.Looper;
Handler handler = new Handler(looper);
BluetoothDiscoveryReceiver receiver = new BluetoothDiscoveryReceiver();
IntentFilter filter = new IntentFilter();
filter.AddAction(BluetoothDevice.ActionFound);
filter.AddAction(BluetoothAdapter.ActionDiscoveryFinished);
filter.AddAction(BluetoothAdapter.ActionDiscoveryStarted);
Platform.CurrentActivity.RegisterReceiver(receiver, filter, null, handler);
EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.AutoReset);
receiver.DeviceFound += (s, e) =>
{
if (!devices.Contains(e))
{
devices.Add(e);
if(devices.Count == maxDevices)
{
((BluetoothAdapter)_radio).CancelDiscovery();
}
}
};
((BluetoothAdapter)_radio).StartDiscovery();
receiver.DiscoveryComplete += (s, e) =>
{
Platform.CurrentActivity.UnregisterReceiver(receiver);
handle.Set();
handlerThread.QuitSafely();
};
handle.WaitOne();
return devices.AsReadOnly();
}
async void PlatformConnect(BluetoothAddress address, Guid service)
{
var nativeDevice = ((BluetoothAdapter)_radio).GetRemoteDevice(address.ToString("C"));
if (!Authenticate && !Encrypt)
{
_socket = nativeDevice.CreateInsecureRfcommSocketToServiceRecord(Java.Util.UUID.FromString(service.ToString()));
}
else
{
_socket = nativeDevice.CreateRfcommSocketToServiceRecord(Java.Util.UUID.FromString(service.ToString()));
}
if (_socket is object)
{
try
{
_socket.Connect();
}
catch(Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
try
{
_socket.Connect();
AndroidNetworkStream.GetAvailable(_socket.InputStream as Android.Runtime.InputStreamInvoker);
}
catch (Exception ex2)
{
System.Diagnostics.Debug.WriteLine(ex2.Message);
_socket = null;
}
}
}
}
void PlatformClose()
{
if (_socket is object)
{
if (_socket.IsConnected)
{
_socket.Close();
}
_socket.Dispose();
_socket = null;
}
}
private bool _authenticate;
bool GetAuthenticate()
{
return _authenticate;
}
void SetAuthenticate(bool value)
{
_authenticate = value;
}
Socket GetClient()
{
return null;
}
bool GetConnected()
{
return _socket is object && _socket.IsConnected;
}
private bool _encrypt = false;
bool GetEncrypt()
{
return _encrypt;
}
void SetEncrypt(bool value)
{
_encrypt = value;
}
TimeSpan GetInquiryLength()
{
return TimeSpan.Zero;
}
void SetInquiryLength(TimeSpan length)
{
}
public string GetRemoteMachineName()
{
if(_socket is object && _socket.IsConnected)
return _socket.RemoteDevice.Name;
return null;
}
NetworkStream PlatformGetStream()
{
if(Connected)
return new AndroidNetworkStream(_socket.InputStream, _socket.OutputStream);
return null;
}
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
}
disposedValue = true;
}
}
// This code added to correctly implement the disposable pattern.
#endregion
}
}