I am not sure exactly what you want to do, but if your intent is to open the Bluetooth settings page, this:
UIApplication.SharedApplication.OpenUrl(new NSUrl("App-Prefs:root=Bluetooth"));
won't work. Apple has at some points allowed this (iOS 8 IIRC) and at other points it has disallowed this (most versions of iOS). See this long SO thread about this issue: How to open Settings programmatically like in Facebook app?
Regardless, there is no need. When iOS detects that your app has created a CBCentralManager type with delegate, iOS will display an alert to the user that allows them to go to the bluetooth settings to enable bluetooth by tapping the "Settings" button in the alert.
As far as always getting state as "Unknown", you need to check the state in the delegate for the CBCentralManager. You cannot use the parameterless CBCentralManager constructor new CBCentralManager();
. Check the apple docs: 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: https://stackoverflow.com/a/36824770/2913599
So try this:
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);
}
}
Bottom line: always create a CBCentralManager object with one of the following constructors:
CBCentralManager(ICBCentralManagerDelegate, DispatchQueue)
CBCentralManager(ICBCentralManagerDelegate, DispatchQueue, CBCentralInitOptions)