如何更改 iOS 上的蓝牙状态是 Xamarin Forms 上的 PowerOn?

How to change state of Bluetooth on iOS is PowerOn on Xamarin Forms?

在iOS,我只能检查蓝牙的状态。我在网络上找到解决方案并使用它。

public class CallBluetoothIphoneService : ICallBlueTooth
{
    public void LaunchBluetoothOnPhone()
    {
        try
        {
            // Is bluetooth enabled?
            var bluetoothManager = new CBCentralManager();
            if (bluetoothManager.State == CBCentralManagerState.PoweredOff|| bluetoothManager.State == CBCentralManagerState.Unknown)
                // Does not go directly to bluetooth on every OS version though, but opens the Settings on most
                UIApplication.SharedApplication.OpenUrl(new NSUrl("App-Prefs:root=Bluetooth"));
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
            throw;
        }
    }
}

但是当我尝试 turn off 蓝牙和测试代码时,蓝牙状态是 "Unknown"。 然后我 运行 代码,设备打开设置,切换按钮颜色为绿色(打开蓝牙),但是当我在代码中检查蓝牙状态时,蓝牙状态是 "Unknown",不是 "Power on".

我正在使用 Xamarin 3.3 并在设备 iOS 版本 12.0 上进行测试。

我不确定你到底想做什么,但如果你打算打开蓝牙设置页面,这:

UIApplication.SharedApplication.OpenUrl(new NSUrl("App-Prefs:root=Bluetooth"));

行不通。 Apple 在某些时候允许这样做(iOS 8 IIRC),而在其他时候不允许这样做(iOS 的大多数版本)。请参阅有关此问题的长 SO 线程:How to open Settings programmatically like in Facebook app?

不管怎样,没必要。当 iOS 检测到您的应用程序创建了带有委托的 CBCentralManager 类型时,iOS 将向用户显示警告,允许他们通过点击 "Settings" 进入蓝牙设置以启用蓝牙警报中的按钮。

就始终获得 "Unknown" 的状态而言,您需要检查 CBCentralManager 的委托中的状态。您不能使用无参数 CBCentralManager 构造函数 new CBCentralManager();。查看苹果文档:https://developer.apple.com/documentation/corebluetooth/cbcentralmanager?language=objc and note that there are only two listed init methods, one that takes delegate and queue parameters, and one that takes delegate, queue, and options parameters, although no one complains if you use the parameterless constructor... but you will never get the correct state if you use it. See:

所以试试这个:

public class CallBluetoothIphoneService : ICallBluetooth
{
    public void LaunchBluetoothOnPhone()
    {
        try
        {
            // Is bluetooth enabled?
            var bluetoothManager = new CBCentralManager(new MySimpleCBCentralManagerDelegate(), DispatchQueue.CurrentQueue);

            // This will always show state "Unknown". You need to check it in the delegate's UpdatedState method
            Console.WriteLine($"State: {bluetoothManager.State.ToString()}");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
    }
}

public class MySimpleCBCentralManagerDelegate : CBCentralManagerDelegate
{
    override public void UpdatedState(CBCentralManager mgr)
    {
        // You can check the state in this delegate method
        Console.WriteLine($"UpdatedState: {mgr.State.ToString()}");

        if (mgr.State == CBCentralManagerState.PoweredOn)
        {
            //Passing in null scans for all peripherals. Peripherals can be targeted by using CBUIIDs
            CBUUID[] cbuuids = null;
            mgr.ScanForPeripherals(cbuuids); //Initiates async calls of DiscoveredPeripheral
            //Timeout after 30 seconds
            var timer = new Timer(30 * 1000);
            timer.Elapsed += (sender, e) => mgr.StopScan();
        }
        else
        {
            //Invalid state -- Bluetooth powered down, unavailable, etc.
            System.Console.WriteLine("Bluetooth is not available");
        }
    }

    public override void DiscoveredPeripheral(CBCentralManager central, CBPeripheral peripheral, NSDictionary advertisementData, NSNumber RSSI)
    {
        Console.WriteLine("Discovered {0}, data {1}, RSSI {2}", peripheral.Name, advertisementData, RSSI);
    }
}

底线:始终使用以下构造函数之一创建 CBCentralManager 对象:

CBCentralManager(ICBCentralManagerDelegate, DispatchQueue)

CBCentralManager(ICBCentralManagerDelegate, DispatchQueue, CBCentralInitOptions)