diff --git a/src/NmeaParser/BluetoothDevice.Android.cs b/src/NmeaParser/BluetoothDevice.Android.cs
index 34bb3f5..a0a51cf 100644
--- a/src/NmeaParser/BluetoothDevice.Android.cs
+++ b/src/NmeaParser/BluetoothDevice.Android.cs
@@ -42,13 +42,15 @@ namespace NmeaParser
public class BluetoothDevice : NmeaDevice
{
private static Java.Util.UUID SERIAL_UUID = Java.Util.UUID.FromString("00001101-0000-1000-8000-00805F9B34FB")!;
- private Android.Bluetooth.BluetoothDevice m_device;
+ private readonly Android.Bluetooth.BluetoothDevice m_device;
private BluetoothSocket? m_socket;
+ private readonly Android.Content.Context? m_context;
///
/// Gets a list of bluetooth devices that supports serial communication
///
/// A set of bluetooth devices available that supports serial connections
+ [Obsolete("Use GetBluetoothSerialDevices(Context)")]
public static IEnumerable GetBluetoothSerialDevices()
{
var adapter = Android.Bluetooth.BluetoothAdapter.DefaultAdapter;
@@ -59,19 +61,58 @@ namespace NmeaParser
}
}
+ ///
+ /// Gets a list of bluetooth devices that supports serial communication
+ ///
+ /// The Android context
+ /// A set of bluetooth devices available that supports serial connections
+ public static IEnumerable GetBluetoothSerialDevices(Android.Content.Context context)
+ {
+ var bluetoothManager = context.GetSystemService(Android.Content.Context.BluetoothService) as BluetoothManager;
+ var adapter = bluetoothManager?.Adapter;
+ if (adapter != null && adapter.IsEnabled && adapter.BondedDevices is not null)
+ {
+ foreach (var b in adapter.BondedDevices.Where(d => d.GetUuids()?.Any(t => SERIAL_UUID.CompareTo(t.Uuid) == 0) == true))
+ yield return b;
+ }
+ }
+
///
/// Initializes a new instance of the class.
///
/// The Android Bluetooth Device.
+ [Obsolete("Use BluetoothDevice(BluetoothDevice, Context)")]
public BluetoothDevice(Android.Bluetooth.BluetoothDevice device)
{
m_device = device ?? throw new ArgumentNullException(nameof(device));
}
-
- ///
- protected override Task OpenStreamAsync()
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Android Bluetooth Device.
+ /// The Android context
+ public BluetoothDevice(Android.Bluetooth.BluetoothDevice device, Android.Content.Context context)
{
- var adapter = Android.Bluetooth.BluetoothAdapter.DefaultAdapter;
+ m_device = device ?? throw new ArgumentNullException(nameof(device));
+ m_context = context ?? throw new ArgumentNullException(nameof(context));
+ }
+
+ ///
+ protected override async Task OpenStreamAsync()
+ {
+ BluetoothAdapter? adapter;
+ if (m_context is not null)
+ {
+ var bluetoothManager = m_context.GetSystemService(Android.Content.Context.BluetoothService) as BluetoothManager;
+ adapter = bluetoothManager?.Adapter;
+ }
+ else
+ {
+#pragma warning disable CS0618 // Type or member is obsolete. Only used if deprecated constructor is used
+ adapter = Android.Bluetooth.BluetoothAdapter.DefaultAdapter;
+#pragma warning restore CS0618 // Type or member is obsolete
+ }
if (adapter?.IsEnabled != true)
throw new InvalidOperationException("Bluetooth Adapter not enabled");
var d = adapter.GetRemoteDevice(m_device.Address);
@@ -80,11 +121,25 @@ namespace NmeaParser
var socket = d.CreateRfcommSocketToServiceRecord(SERIAL_UUID);
if (socket == null)
throw new InvalidOperationException($"Failed to create socket");
- socket.Connect();
+ try
+ {
+ await socket.ConnectAsync();
+ }
+ catch (Java.IO.IOException)
+ {
+ // This sometimes fails. Use fallback approach to open socket
+ // Based on https://stackoverflow.com/a/41627149
+ socket?.Dispose();
+ var m = d.Class?.GetMethod("createRfcommSocket", new Java.Lang.Class[] { Java.Lang.Integer.Type! })!;
+ if (m is null)
+ throw;
+ socket = (Android.Bluetooth.BluetoothSocket)m.Invoke(d, new Java.Lang.Object[] { 1 })!;
+ socket.Connect();
+ }
m_socket = socket;
if (socket.InputStream == null)
throw new InvalidOperationException($"Failed to create socket input stream");
- return Task.FromResult(socket.InputStream);
+ return socket.InputStream;
}
///
diff --git a/src/NmeaParser/NmeaParser.csproj b/src/NmeaParser/NmeaParser.csproj
index 298481b..7485663 100644
--- a/src/NmeaParser/NmeaParser.csproj
+++ b/src/NmeaParser/NmeaParser.csproj
@@ -31,6 +31,7 @@
enable
logo.png
+ false
diff --git a/src/NmeaParser/SystemNmeaDevice.Android.cs b/src/NmeaParser/SystemNmeaDevice.Android.cs
index cb22a49..ea119dc 100644
--- a/src/NmeaParser/SystemNmeaDevice.Android.cs
+++ b/src/NmeaParser/SystemNmeaDevice.Android.cs
@@ -68,7 +68,11 @@ namespace NmeaParser
stream = new StringStream();
listener = new Listener();
listener.NmeaMessage += (s, e) => stream?.Append(e);
+#if MONOANDROID50
bool success = manager.AddNmeaListener(listener);
+#else
+ bool success = manager.AddNmeaListener(listener, null);
+#endif
manager.RequestLocationUpdates(LocationManager.GpsProvider, 0, 0f, listener );
return Task.FromResult(stream);
}
@@ -76,10 +80,13 @@ namespace NmeaParser
///
protected override Task CloseStreamAsync(Stream stream)
{
- manager.RemoveUpdates(listener);
- manager.RemoveNmeaListener(listener);
- listener?.Dispose();
- listener = null;
+ if (listener is not null)
+ {
+ manager.RemoveUpdates(listener);
+ manager.RemoveNmeaListener(listener);
+ listener.Dispose();
+ listener = null;
+ }
stream.Dispose();
return Task.CompletedTask;
}
diff --git a/src/SampleApp.Droid/MainActivity.cs b/src/SampleApp.Droid/MainActivity.cs
index 397c97d..dd28e8b 100644
--- a/src/SampleApp.Droid/MainActivity.cs
+++ b/src/SampleApp.Droid/MainActivity.cs
@@ -1,4 +1,5 @@
using Android;
+using Android.Bluetooth;
using Android.Content.PM;
using AndroidX.Core.App;
@@ -32,15 +33,15 @@ public class MainActivity : Activity
return;
}
- foreach (var d in NmeaParser.BluetoothDevice.GetBluetoothSerialDevices())
+ foreach (var d in NmeaParser.BluetoothDevice.GetBluetoothSerialDevices(ApplicationContext))
{
- devices[d.Name + " " + d.Address] = d.Address;
+ devices[d.Name + " " + d.Address] = d;
}
devicePicker.Adapter = new ArrayAdapter(this, Android.Resource.Layout.SimpleSpinnerDropDownItem, devices.Keys.ToArray());
devicePicker.SetSelection(0);
}
- private Dictionary devices = new Dictionary();
+ private Dictionary devices = new Dictionary();
private void StopButton_Click(object? sender, EventArgs e)
{
@@ -100,25 +101,27 @@ public class MainActivity : Activity
{
try
{
- status.Text = "Opening bluetooth...";
- var adapter = Android.Bluetooth.BluetoothAdapter.DefaultAdapter;
- var bt = Android.Bluetooth.BluetoothAdapter.DefaultAdapter.GetRemoteDevice(btAddress);
- Java.Util.UUID SERIAL_UUID = Java.Util.UUID.FromString("00001101-0000-1000-8000-00805F9B34FB"); //UUID for Serial Device Service
- socket = bt.CreateRfcommSocketToServiceRecord(SERIAL_UUID);
- try
- {
- await socket.ConnectAsync();
- }
- catch (Java.IO.IOException)
- {
- // This sometimes fails. Use fallback approach to open socket
- // Based on https://stackoverflow.com/a/41627149
- socket?.Dispose();
- var m = bt.Class.GetMethod("createRfcommSocket", new Java.Lang.Class[] { Java.Lang.Integer.Type });
- socket = (Android.Bluetooth.BluetoothSocket)m.Invoke(bt, new Java.Lang.Object[] { 1 })!;
- socket.Connect();
- }
- listener = new NmeaParser.StreamDevice(socket.InputStream);
+ listener = new NmeaParser.BluetoothDevice(btAddress, ApplicationContext!);
+ //status.Text = "Opening bluetooth...";
+ //var bluetoothManager = ApplicationContext!.GetSystemService(Android.Content.Context.BluetoothService) as Android.Bluetooth.BluetoothManager;
+ //var adapter = bluetoothManager?.Adapter;
+ //var bt = adapter.GetRemoteDevice(btAddress);
+ //Java.Util.UUID SERIAL_UUID = Java.Util.UUID.FromString("00001101-0000-1000-8000-00805F9B34FB"); //UUID for Serial Device Service
+ //socket = bt.CreateRfcommSocketToServiceRecord(SERIAL_UUID);
+ //try
+ //{
+ // await socket.ConnectAsync();
+ //}
+ //catch (Java.IO.IOException)
+ //{
+ // // This sometimes fails. Use fallback approach to open socket
+ // // Based on https://stackoverflow.com/a/41627149
+ // socket?.Dispose();
+ // var m = bt.Class.GetMethod("createRfcommSocket", new Java.Lang.Class[] { Java.Lang.Integer.Type });
+ // socket = (Android.Bluetooth.BluetoothSocket)m.Invoke(bt, new Java.Lang.Object[] { 1 })!;
+ // socket.Connect();
+ //}
+ //listener = new NmeaParser.StreamDevice(socket.InputStream);
}
catch (System.Exception ex)
{
@@ -132,11 +135,23 @@ public class MainActivity : Activity
{
listener.MessageReceived += Listener_MessageReceived;
status!.Text += "\nOpening device...";
- await listener.OpenAsync();
- status.Text += "\nConnected!";
- startButton.Enabled = !(stopButton.Enabled = true);
- monitor = new NmeaParser.Gnss.GnssMonitor(listener);
- monitor.LocationChanged += Monitor_LocationChanged;
+ try
+ {
+ await listener.OpenAsync();
+ status.Text += "\nConnected!";
+ monitor = new NmeaParser.Gnss.GnssMonitor(listener);
+ monitor.LocationChanged += Monitor_LocationChanged;
+ startButton.Enabled = !(stopButton.Enabled = true);
+ }
+ catch (Exception ex)
+ {
+ status.Text += "\nError opening device:\n" + ex.Message;
+ startButton.Enabled = true;
+ stopButton.Enabled = false;
+ }
+ finally
+ {
+ }
}
else
{