You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

迁移至MAUI的iOS应用如何获取蓝牙权限?

MAUI iOS 蓝牙权限请求无法触发弹窗的解决方法

问题背景

将Xamarin.Forms应用迁移至MAUI后,iOS端创建CBCentralManager实例后状态始终为CBManagerState.Unknown,无法触发蓝牙权限请求弹窗,原Xamarin.Forms中的权限请求逻辑失效。原iOS项目已在info.plist中配置了以下权限字符串:

NSBluetoothPeripheralUsageDescription
NSBluetoothAlwaysUsageDescription
Privacy - Bluetooth Peripheral Usage Description
Privacy - Bluetooth Always Usage Description

原权限请求逻辑(更新后):

public async Task<bool> RequestBluetoothPermission()
{
    //iOS 13.0 and below
    if (!UIDevice.CurrentDevice.CheckSystemVersion(13, 1))
    {
        return true;
    }

    //iOS 13.1 and above
    if (CBManager.Authorization == CBManagerAuthorization.NotDetermined)
    {
        TaskCompletionSource<CBCentralManagerState> tcs = new TaskCompletionSource<CBCentralManagerState>();
        Action<CBCentralManagerState> handleBluetoothStateChangedForFirstTime = delegate (CBCentralManagerState bluetoothState)
       {
           HandleBluetoothStateChanged(bluetoothState);
           tcs.TrySetResult(bluetoothState);
       };

        var simpleCBCentralManagerDelegate = new SimpleCBCentralManagerDelegate();
        simpleCBCentralManagerDelegate.StateChanged += handleBluetoothStateChangedForFirstTime;

        _cBCentralManager = new CBCentralManager(simpleCBCentralManagerDelegate, null, new CBCentralInitOptions() { ShowPowerAlert = false });
        var status = await tcs.Task;

        simpleCBCentralManagerDelegate.StateChanged -= handleBluetoothStateChangedForFirstTime;
        simpleCBCentralManagerDelegate.StateChanged += HandleBluetoothStateChanged;

        return status != CBCentralManagerState.Unauthorized;
    }

    // In any else case we can't ask again so we just return the current permission status
    return CBManager.Authorization == CBManagerAuthorization.AllowedAlways;
}

解决步骤

1. 修正info.plist权限配置

MAUI中iOS的权限配置需在Platforms/iOS/Info.plist中添加标准键值对,无需保留带Privacy -前缀的旧写法,同时确保权限描述内容不为空:

<key>NSBluetoothAlwaysUsageDescription</key>
<string>需要蓝牙权限连接并管理外设</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>需要蓝牙权限扫描附近外设</string>

注:iOS 13及以上版本主要依赖NSBluetoothAlwaysUsageDescription,保留旧键是为了兼容更低版本系统。

2. 重构权限请求逻辑

MAUI中需确保CBCentralManager实例被正确持有,且状态回调能被可靠触发,修改后的代码如下:

private CBCentralManager? _centralManager;
private TaskCompletionSource<CBManagerAuthorization>? _authTaskSource;

public async Task<bool> RequestBluetoothPermission()
{
    // iOS 13.0及以下无需主动请求权限
    if (!UIDevice.CurrentDevice.CheckSystemVersion(13, 1))
    {
        return true;
    }

    var currentAuth = CBManager.Authorization;
    // 已授权或拒绝,直接返回当前状态
    if (currentAuth != CBManagerAuthorization.NotDetermined)
    {
        return currentAuth == CBManagerAuthorization.AllowedAlways;
    }

    _authTaskSource = new TaskCompletionSource<CBManagerAuthorization>();
    var authDelegate = new BluetoothAuthDelegate();
    authDelegate.OnAuthorizationUpdated += HandleAuthUpdate;

    // 初始化CBCentralManager,绑定主线程队列避免回调丢失
    _centralManager = new CBCentralManager(authDelegate, DispatchQueue.MainQueue, new CBCentralInitOptions
    {
        ShowPowerAlert = false
    });

    // 等待权限请求结果
    var finalAuth = await _authTaskSource.Task;
    authDelegate.OnAuthorizationUpdated -= HandleAuthUpdate;

    return finalAuth == CBManagerAuthorization.AllowedAlways;
}

private void HandleAuthUpdate(CBManagerAuthorization status)
{
    _authTaskSource?.TrySetResult(status);
}

// 自定义Delegate监听权限状态
private class BluetoothAuthDelegate : CBCentralManagerDelegate
{
    public event Action<CBManagerAuthorization>? OnAuthorizationUpdated;

    public override void UpdatedState(CBCentralManager central)
    {
        OnAuthorizationUpdated?.Invoke(CBManager.Authorization);
    }
}

3. 核心注意事项

  • 持有CBCentralManager实例:必须在类级别声明变量(如_centralManager)持有实例,避免被垃圾回收导致回调不触发。
  • 指定有效队列:初始化时绑定DispatchQueue.MainQueue或其他有效队列,防止因队列问题丢失状态回调。
  • 监听UpdatedState方法:iOS蓝牙权限状态变化会通过该方法通知,需在此处获取最新授权状态。
  • 避免重复请求:仅当CBManager.Authorization为NotDetermined时发起请求,否则直接返回当前状态。

内容的提问来源于stack exchange,提问作者o_w

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 00:25:27