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

.NET MAUI安卓端蓝牙LE运行时权限检查与设置实现

.NET MAUI 安卓平台蓝牙LE运行时权限实现方案

不要在页面构造函数中执行权限申请、蓝牙扫描这类异步逻辑,构造函数执行时页面还未完成挂载,此时弹权限弹窗会出现上下文异常,相关逻辑应该放到页面的OnAppearing生命周期方法中触发。

安卓不同版本的蓝牙权限要求差异很大:安卓6.0到11(API23-30)蓝牙扫描依赖定位权限,安卓12(API31)及以上版本替换成了独立的蓝牙扫描、连接权限,MAUI内置的Permissions API没有覆盖这套新权限,我们可以通过自定义权限类统一适配,不需要自己手写分支判断SDK版本。


1. 自定义蓝牙权限类

继承MAUI提供的Permissions.BasePlatformPermission基类,实现跨版本的权限声明配置,这个类可以放在共享项目的任意目录下:

public class BluetoothLEPermissions : Permissions.BasePlatformPermission
{
    public override (string androidPermission, bool isRuntime)[] RequiredPermissions
    {
        get
        {
            var permissionList = new List<(string, bool)>();
            
            if (OperatingSystem.IsAndroidVersionAtLeast(31))
            {
                // 安卓12+ 专属蓝牙运行时权限
                permissionList.Add(("android.permission.BLUETOOTH_SCAN", true));
                permissionList.Add(("android.permission.BLUETOOTH_CONNECT", true));
                // 需要蓝牙广播功能就放开下面这行
                // permissionList.Add(("android.permission.BLUETOOTH_ADVERTISE", true));
            }
            else
            {
                // 安卓6-11 蓝牙扫描需要定位权限
                permissionList.Add(("android.permission.ACCESS_FINE_LOCATION", true));
            }

            // 旧版本系统兼容的基础蓝牙权限,不需要动态申请
            permissionList.Add(("android.permission.BLUETOOTH", false));
            permissionList.Add(("android.permission.BLUETOOTH_ADMIN", false));
            
            return permissionList.ToArray();
        }
    }
}

2. 权限检测与申请逻辑

自定义权限类可以直接复用MAUI原生的Permissions API,不需要自己调用安卓原生的权限检测方法:

  • 权限检测:调用Permissions.CheckStatusAsync<BluetoothLEPermissions>()就能直接拿到当前应用的蓝牙权限状态,自动适配不同安卓版本
  • 权限申请:未授权时调用Permissions.RequestAsync<BluetoothLEPermissions>(),系统会自动弹出原生权限申请弹窗,不需要自己写自定义Alert提前询问用户
  • 永久拒绝处理:如果用户勾选了“不再询问”拒绝权限,后续调用申请方法不会再弹弹窗,需要引导用户跳转到系统设置页手动开启权限

3. 页面完整实现代码

把原来写在构造函数里的逻辑迁移到OnAppearing生命周期方法中,参考实现如下:

using Android.OS;

namespace TSDZ2Monitor.Pages;

public partial class BluetoothPage : ContentPage
{
    public BluetoothPage()
    {
        InitializeComponent();
        Console.WriteLine("Bluetooth here");
    }

    protected override async void OnAppearing()
    {
        base.OnAppearing();
        await CheckBluetoothPermissionAndStartScan();
    }

    private async Task CheckBluetoothPermissionAndStartScan()
    {
        // 先检查现有权限状态
        var permissionStatus = await Permissions.CheckStatusAsync<BluetoothLEPermissions>();
        if (permissionStatus == PermissionStatus.Granted)
        {
            StartBleScan();
            return;
        }

        // 发起权限申请
        permissionStatus = await Permissions.RequestAsync<BluetoothLEPermissions>();
        if (permissionStatus == PermissionStatus.Granted)
        {
            StartBleScan();
            return;
        }

        // 处理权限拒绝场景
        if (DeviceInfo.Platform == DevicePlatform.Android)
        {
            // 判断是否是永久拒绝(用户选了不再询问)
            bool needShowRationale = await Permissions.ShouldShowRationaleAsync<BluetoothLEPermissions>();
            if (!needShowRationale)
            {
                bool goToSettings = await DisplayAlert("权限不足", "蓝牙权限已被永久拒绝,请前往应用设置页手动开启权限后使用", "去设置", "取消");
                if (goToSettings)
                {
                    // 跳转到应用系统设置页
                    AppInfo.ShowSettingsUI();
                }
                return;
            }
        }

        // 普通拒绝场景,提示权限用途
        await DisplayAlert("权限不足", "需要蓝牙权限才能扫描周边的心率带等外设设备,拒绝授权将无法使用对应功能", "确定");
    }

    private void StartBleScan()
    {
        // 这里写Plugin.BLE的设备扫描逻辑即可
        Console.WriteLine("启动蓝牙扫描");
    }
}

补充说明

你之前在AndroidManifest.xml里添加的权限声明已经覆盖了所有版本的需求,如果你的应用不需要通过蓝牙扫描获取物理位置,可以给BLUETOOTH_SCAN权限加上neverForLocation标记,避免应用商店审核时要求你提供位置权限的使用说明:

<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />

如果你采用MVVM架构,也可以把权限检查逻辑放到ViewModel中,只要通过页面的OnAppearing事件触发对应命令即可,不要在ViewModel构造函数中执行异步权限操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 12:54:16