我正在尝试连接到我的低功耗蓝牙设备。找到设备并获取外围对象后。我无法从我的 iPhone 连接到蓝牙设备,它也没有调用 central.ConnectedPeripheral 方法。
另一个问题是我无法在方法中注册事件 central.ConnectedPeripheral += ConnectedPeripheral。
错误:System.InvalidOperationException:事件注册正在覆盖现有委托(delegate)。要么只使用事件,要么使用你自己的委托(delegate):
class IOSBluetooth : IBluetooth
{
private readonly CBCentralManager central;
private CBPeripheral activePeripheral;
SimpleCBCentralManagerDelegate myCentralDelegate;
public bool IsScanning { get; private set; }
List<CBPeripheral> connectedDevices = new List<CBPeripheral>();
//List<CBPeripheral> discoveredDevices = new List<CBPeripheral>();
/// <summary>
/// Gets the current Bluetooth instance
/// </summary>
/// <value>The Bluetooth Adapter instance</value>
public IOSBluetooth(SimpleCBCentralManagerDelegate myCenDel)
{
myCentralDelegate = myCenDel;
central = new CBCentralManager(myCentralDelegate, DispatchQueue.CurrentQueue);
InitializeEvents();
// central.DiscoveredPeripheral += DiscoveredPeripheral; // Called when peripheral is discovered (Working)
// central.UpdatedState += UpdatedState; // Method Implemented - Tells us about the bluetooth powered state (On or Off). (Working)
// central.ConnectedPeripheral += ConnectedPeripheral; // Devices that are connected to Iphone -> Services and Characteristics discovery start from here
// central.DisconnectedPeripheral += DisconnectedPeripheral; // Disconnect the device from the iphone
// central.FailedToConnectPeripheral += FailedToConnectPeripheral; // Failed to connect to Bluetooth Device
}
void InitializeEvents()
{
try
{
// central.ConnectedPeripheral += ConnectedPeripheral;
central.FailedToConnectPeripheral += FailedToConnectPeripheral;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message, "Intialization Failes");
Console.WriteLine("Bluetooth.Connect " + ex.Message);
}
}
public void FailedToConnectPeripheral(object sender, CBPeripheralErrorEventArgs e)
{
Console.WriteLine("Failed to Connect to Peripheral");
}
private void DisconnectedPeripheral(object sender, CBPeripheralErrorEventArgs e)
{
// when a peripheral disconnects, remove it from our running list.
if (connectedDevices.Contains(e.Peripheral))
{
connectedDevices.Remove(e.Peripheral);
}
}
public void ConnectToPeripheral(CBPeripheral peripheral)
{
central.ConnectPeripheral(peripheral, new PeripheralConnectionOptions { NotifyOnConnection = true, NotifyOnDisconnection = true, NotifyOnNotification = true });
}
private void UpdatedState(object sender, EventArgs e)
{
throw new NotImplementedException();
}
//public override void DiscoveredPeripheral(object sender, CBDiscoveredPeripheralEventArgs e)
//{
// Console.WriteLine("DiscoveredPeripheral: {0}", e.Peripheral.Name);
// discoveredDevices.Add(e.Peripheral);
//}
public void ConnectedPeripheral(object sender, CBPeripheralEventArgs e)
{
if (!connectedDevices.Contains(e.Peripheral))
{
connectedDevices.Add(e.Peripheral);
}
activePeripheral = e.Peripheral;
Console.WriteLine("Connected to " + activePeripheral.Name);
if (activePeripheral.Delegate == null)
{
activePeripheral.Delegate = new SimplePeripheralDelegate();
//Begins asynchronous discovery of services
activePeripheral.DiscoverServices();
}
}
public async void BeginScanningForDevices()
{
Console.WriteLine("BluetoothLEManager: Starting a scan for devices.");
// start scanning
IsScanning = true;
central.ScanForPeripherals((CBUUID[])null); // Discover all the devices and Initiates async calls of DiscoveredPeripheral
// in 10 seconds, stop the scan
await Task.Delay(10000);
// if we're still scanning
if (IsScanning)
{
Console.WriteLine("BluetoothLEManager: Scan timeout has elapsed.");
StopScanningForDevices();
}
}
/// <summary>
/// Stops the Central Bluetooth Manager from scanning for more devices. Automatically
/// called after 10 seconds to prevent battery drain.
/// </summary>
public void StopScanningForDevices()
{
Console.WriteLine("BluetoothLEManager: Stopping the scan for devices.");
IsScanning = false;
central.StopScan();
}
public IEnumerable<string> ListDevices()
{
return myCentralDelegate.DiscoveredDevices.Keys;
}
public bool Connect(string DeviceName)
{
StopScanningForDevices();
if (!myCentralDelegate.DiscoveredDevices.ContainsKey(DeviceName))
return false;
var device = myCentralDelegate.DiscoveredDevices[DeviceName];
// central.ConnectPeripheral(device, new PeripheralConnectionOptions { NotifyOnConnection = true, NotifyOnDisconnection = true, NotifyOnNotification = true });
central.ConnectPeripheral(device);
return true;
}
public void StartScanning()
{
if(central.State == (CBCentralManagerState.PoweredOn))
BeginScanningForDevices();
}
public void StopScanning()
{
StopScanningForDevices();
}
}
请您参考如下方法:
要消除“错误:System.InvalidOperationException:事件注册正在覆盖现有委托(delegate)。要么只使用事件,要么使用您自己的委托(delegate)”错误,请在 SimpleCBCentralManagerDelegate 中实现 类。该类被用作 iOS 委托(delegate)(不要与 C# ConnectedPeripheral 方法delegate 混淆)所以来自 CBCentralManager central 的所有事件都在相关方法中处理SimpleCBCentralManagerDelegate 类。
这里的想法是,您可以使用 iOS 样式委托(delegate)/协议(protocol)模式,其中实现 Obj-C/iOS 协议(protocol)的委托(delegate)类被指定为将调用这些协议(protocol)的类的 iOS/Obj-C 委托(delegate)协议(protocol)方法,或者您可以使用 C# 样式的事件订阅,但不能在同一个对象上同时使用这两种方法。
更多信息在本文档中讨论:https://learn.microsoft.com/en-us/xamarin/ios/app-fundamentals/delegates-protocols-and-events 这是一本很长的书,但如果您正在使用 Xamarin.iOS 进行开发,那么它非常值得。
