.NET MAUI - UI von Bluetooth -Ereignissen aktualisieren
Posted: 02 Feb 2025, 18:48
Ich versuche, meine alte Xamarin -Android -Bluetooth -App in .NET MAUI umzuschreiben. Ich habe jedoch anscheinend Schwierigkeiten, die Blazor -Benutzeroberfläche zu aktualisieren, wenn ich Bluetooth -Ereignisse erhalte (wie DiscoveryStarted , DeviceFound , Discoveryfinished ). Während sich die Daten in der Sammlung ändert oder der Status eines Bools innerhalb der Komponenten ändert, wird die Benutzeroberfläche nicht aktualisiert. Rufen Sie an, die Ansicht aktualisiert nicht. Ich muss ausdrücklich StateHaschanged überall im Hintergrund bezeichnen.
Was ist der beste Weg, um damit umzugehen? Ich muss es vorziehen, all diese invokeasync und statehaschanged Anrufe zu schreiben. class = "Lang-none hübschprint-override">
Der BluetoothService , der hier injiziert wird
und die Bluetootootoothere für Android
stattdessen, aber ich habe die gleichen Ergebnisse
Was ist der beste Weg, um damit umzugehen? Ich muss es vorziehen, all diese invokeasync und statehaschanged Anrufe zu schreiben. class = "Lang-none hübschprint-override">
Code: Select all
@inject IBluetoothService bluetoothService;
@{
if (isDiscovering)
{
Stop Discovery
}
else
{
Start Discovery
}
}
[list]
@foreach (var device in devices)
{
[*]@device
}
[/list]
@code
{
private bool isDiscovering = false;
private ObservableCollection devices = new();
private async Task StartDiscovery()
{
isDiscovering = true;
await bluetoothService.StartDiscovery(OnDeviceDiscovered, OnDiscoveryFinished);
}
private async Task OnDeviceDiscovered(string deviceName)
{
await InvokeAsync(() =>
{
devices.Add(deviceName);
StateHasChanged(); // Have to do this before the UI updates
});
}
private async Task OnDiscoveryFinished()
{
await InvokeAsync(() =>
{
isDiscovering = false;
StateHasChanged(); // Have to do this before the UI updates
});
}
private void StopDiscovery()
{
isDiscovering = false;
}
}
Code: Select all
internal class BluetoothService : IBluetoothService
{
private readonly BluetoothAdapter? bluetoothAdapter = BluetoothAdapter.DefaultAdapter;
private readonly global::Android.Content.Context context;
CustomCode.BluetoothReceiver? bluetoothReceiver = new();
public bool IsDiscovering { get; private set; }
public BluetoothService()
{
context = global::Microsoft.Maui.ApplicationModel.Platform.CurrentActivity
?? global::Microsoft.Maui.MauiApplication.Context;
if (bluetoothAdapter == null || !bluetoothAdapter.IsEnabled)
throw new Exception("Bluetooth not available/enabled");
bluetoothReceiver = new BluetoothReceiver();
bluetoothReceiver.DiscoveryStarted += BluetoothReceiver_DiscoveryStarted;
bluetoothReceiver.DiscoveryFinished += BluetoothReceiver_DiscoveryFinished;
bluetoothReceiver.DeviceFound += BluetoothReceiver_DeviceFound;
foreach (var action in new[] { BluetoothDevice.ActionFound, BluetoothAdapter.ActionDiscoveryStarted, BluetoothAdapter.ActionDiscoveryFinished, BluetoothDevice.ActionBondStateChanged })
context.RegisterReceiver(bluetoothReceiver, new global::Android.Content.IntentFilter(action));
}
private Func deviceFound;
private Func discoveryFinished;
public Task StartDiscovery(Func deviceFound, Func discoveryFinished)
{
if (IsDiscovering) throw new InvalidOperationException();
IsDiscovering = true;
this.deviceFound = deviceFound;
this.discoveryFinished = discoveryFinished;
//BluetoothDevices.Clear();
ActivityCompat.RequestPermissions(global::Microsoft.Maui.ApplicationModel.Platform.CurrentActivity!, [
global::Android.Manifest.Permission.Bluetooth,
global::Android.Manifest.Permission.BluetoothAdmin,
global::Android.Manifest.Permission.BluetoothAdvertise,
global::Android.Manifest.Permission.BluetoothConnect,
global::Android.Manifest.Permission.BluetoothPrivileged,
global::Android.Manifest.Permission.BluetoothScan,
global::Android.Manifest.Permission.AccessCoarseLocation,
global::Android.Manifest.Permission.AccessFineLocation,
//"android.hardware.sensor.accelerometer"
], 1);
return Task.CompletedTask;
}
private async void BluetoothReceiver_DeviceFound(object? sender, Platforms.Android.CustomCode.EventArgs.DeviceFoundEventArgs e)
{
if (e.Device?.Name is string name)
await deviceFound(name);
// Binding to this collection, and updating it is pointless
//BluetoothDevices.Add(name);
}
private void BluetoothReceiver_DiscoveryFinished(object? sender, EventArgs e)
{
// Binding to this variable, and updating it is pointless
IsDiscovering = false;
discoveryFinished();
}
private void BluetoothReceiver_DiscoveryStarted(object? sender, EventArgs e) { }
}
Code: Select all
internal class BluetoothReceiver : BroadcastReceiver
{
public override void OnReceive(Context? context, Intent? intent)
{
switch (intent?.Action)
{
case BluetoothDevice.ActionFound:
if (intent.GetParcelableExtra(BluetoothDevice.ExtraDevice) is BluetoothDevice device)
OnDeviceFound(new EventArgs.DeviceFoundEventArgs { Device = device });
break;
case BluetoothAdapter.ActionDiscoveryStarted:
OnDiscoveryStarted(System.EventArgs.Empty);
break;
case BluetoothAdapter.ActionDiscoveryFinished:
OnDiscoveryFinished(System.EventArgs.Empty);
break;
case BluetoothDevice.ActionBondStateChanged:
if (intent.GetParcelableExtra(BluetoothDevice.ExtraDevice) is BluetoothDevice device2)
{
var oldState = (Bond)(int)intent.GetParcelableExtra(BluetoothDevice.ExtraPreviousBondState);
var newState = (Bond)(int)intent.GetParcelableExtra(BluetoothDevice.ExtraBondState);
OnBondStateChanged(new EventArgs.BondStateChangedEventArgs { Device = device2, OldState = oldState, NewState = newState });
}
break;
case BluetoothDevice.ActionUuid:
if (intent.GetParcelableExtra(BluetoothDevice.ExtraUuid) is UUID uuid)
OnUUIDFetched(new EventArgs.UuidFetchedEventArgs { UUID = uuid });
break;
}
}
#region DeviceFound
public event EventHandler DeviceFound;
protected void OnDeviceFound(EventArgs.DeviceFoundEventArgs e)
{
if (DeviceFound != null)
DeviceFound(this, e);
}
#endregion
#region DiscoveryStarted
public event EventHandler? DiscoveryStarted;
protected void OnDiscoveryStarted(System.EventArgs e)
{
if (DiscoveryStarted != null)
DiscoveryStarted(this, e);
}
#endregion
#region DiscoveryFinished
public event EventHandler? DiscoveryFinished;
protected void OnDiscoveryFinished(System.EventArgs e)
{
if (DiscoveryFinished != null)
DiscoveryFinished(this, e);
}
#endregion
#region BondStateChanged
public event EventHandler? BondStateChanged;
protected void OnBondStateChanged(EventArgs.BondStateChangedEventArgs e)
{
if (BondStateChanged != null)
BondStateChanged(this, e);
}
#endregion
#region UuidFetched
public event EventHandler? UuidFetched;
protected void OnUUIDFetched(EventArgs.UuidFetchedEventArgs e)
{
if (UuidFetched != null)
UuidFetched(this, e);
}
#endregion
}
< /code>
Bearbeiten: < /p>
Ich habe versucht, < /p>
zu verwendenMainThread.BeginInvokeOnMainThread(() => BluetoothDevices.Add(name));