【问题标题】:How do I check is my app ios has Bluetooth permission in Xamarin.ios?如何检查我的应用程序 ios 在 Xamarin.ios 中是否具有蓝牙权限?
【发布时间】:2021-08-09 03:54:28
【问题描述】:

我需要检查我的Xamarin.Forms 应用是否有蓝牙权限,如果没有,我想申请。我已经能够将它实现为 Android 的依赖服务,但我不知道如何为 iOS 实现它。我看到一些文章提到了它在 ios 13 与早期版本上的工作方式之间的一些差异,但它们并不是很清楚。

我尝试使用以下代码在运行 ios 12.2 的 iPhone 6s 上进行检查和测试:

var manager = new CBCentralManager();
return (CBCentralManager.Authorization) == CBManagerAuthorization.AllowedAlways;

但它会抛出一个MonoTouchException。如何检查权限以及如何请求权限?以及如何处理不同版本 ios 的需求? (早在 ios 11)。

【问题讨论】:

    标签: xamarin xamarin.forms xamarin.ios bluetooth-lowenergy core-bluetooth


    【解决方案1】:

    Apple introduced bluetooth 来自 iOS 13 的许可。

    因此,对于 iOS 12 及更低版本,您无需请求或检查蓝牙权限。

    要启用蓝牙,必须在 plist 文件中添加两个键。隐私 — 蓝牙外围设备使用说明和隐私 — 蓝牙始终使用说明。请说明您为什么要在应用中使用蓝牙。

    Xamarin.Forms 共享 PCL 代码

    依赖服务接口

    public interface IPermissionService
    {
        bool HasBluetoothPermission();
        void RequestBluetoothPermission(Action bluetoothAction);
    }
    
    

    查看状态和请求蓝牙权限的UI页面

    <ContentPage
        xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        x:Class="StackQA2XF.BluetoothPermissionPage">
        <ContentPage.Content>
            <StackLayout Orientation="Vertical" Spacing="50" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
                <StackLayout Orientation="Horizontal" HeightRequest="60" >
                    <Button Text="Has Bluetooth Permission" Clicked="HasBluetooth_Clicked" />
                    <Label x:Name="LabelHasPermission" VerticalOptions="Center" FontSize="Micro" Margin="10,0,0,0" TextColor="OrangeRed" Text="No" />
                </StackLayout>
                <Button Text="Request Bluetooth Permission" Clicked="RequestBluetooth_Clicked"/>
            </StackLayout>
        </ContentPage.Content>
    </ContentPage>
    
    public partial class BluetoothPermissionPage : ContentPage
    {
        readonly IPermissionService service;
    
        public BluetoothPermissionPage()
        {
            InitializeComponent();
            service = DependencyService.Get<IPermissionService>();
        }
    
        protected override void OnAppearing()
        {
            base.OnAppearing();
            CheckBluetooothPermission();
        }
    
        void HasBluetooth_Clicked(System.Object sender, System.EventArgs e)
        {
            CheckBluetooothPermission();
        }
    
        private void CheckBluetooothPermission()
        {
            LabelHasPermission.Text = service.HasBluetoothPermission() ? "YES" : "NO";
        }
    
        void RequestBluetooth_Clicked(System.Object sender, System.EventArgs e)
        {
            service.RequestBluetoothPermission(() =>
            {
                CheckBluetooothPermission();
            });
        }
    }
    

    iOS平台端(原生代码)

    依赖服务实现。

    [assembly: Dependency(typeof(StackQA2XF.iOS.Service.PermissionService))]
    namespace StackQA2XF.iOS.Service
    {
        public class PermissionService : IPermissionService
        {
            Action? _bluetoothAction = null; //Optional, if you wanted to notify user that you have performed action (allow or deny) on the permission request dialog
    
            public bool HasBluetoothPermission()
            {
                if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
                {
                    return CBCentralManager.Authorization == CBManagerAuthorization.AllowedAlways;
                }
                else
                {
                    return true;
                }
            }
    
            public void RequestBluetoothPermission(Action bluetoothAction)
            {
                _bluetoothAction = bluetoothAction;
                var myDelegate = new PermissionCBCentralManager(this);
                var centralManger = new CBCentralManager(myDelegate, DispatchQueue.MainQueue, new CBCentralInitOptions() { ShowPowerAlert = false });
            }
    
            internal void CurrentUpdatedState(CBCentralManager central)
            {
                _bluetoothAction?.Invoke();
            }
        }
    
        public class PermissionCBCentralManager : CBCentralManagerDelegate
        {
            PermissionService permissionService = null;
    
            public PermissionCBCentralManager(PermissionService controller)
            {
                permissionService = controller;
            }
    
            public override void UpdatedState(CBCentralManager central)
            {
                permissionService.CurrentUpdatedState(central);
            }
        }
    }
    

    Info.plist

    为了向后支持旧 iOS 版本, NSBluetoothPeripheralUsageDescription 需要在 info.plist 中定义

    注意:如果CBCentralManager.ShowPowerAlert is true,当用户蓝牙设置为OFF时,会导致设备蓝牙设置显示ON的系统对话框。 IE。 CBCentralManager.ShowPowerAlert is true 如果蓝牙权限关闭或您的应用程序和您的 iPhone 中的蓝牙功能已关闭,将产生两个对话框。

    ShowPowerAlert is false 时,不会显示此系统对话框。

    不要使用模拟器来检查这个实现。

    权限请求对话框将出现在 iOS 13 及更高版本中。

    在 iOS 中,权限为 request dialog will display only once。因此,只有在第一次安装后,单击“请求蓝牙权限”时才能看到蓝牙权限请求对话框。一旦您拒绝并且稍后第二次单击“请求蓝牙权限”按钮时,将不会显示权限请求对话框。您可以通过显示带有按钮的自定义对话框来导航到应用程序的设置来处理这些场景。

    请使用此测试应用程序供您参考LINK

    【讨论】:

    • 从哪里获得 PermissionProvider 类?您在哪里创建变量 _bluetoothAction?
    • @Kikanye 我已经更新了我的答案。这个答案解决了你的问题吗?
    • 将在 2 天内对此进行测试
    • @Kikanye 如果你知道如何使用依赖服务。那么已经写好的答案应该可以工作。我已经用完整的实现(使用依赖服务)更新了答案。我已经在新的示例项目中测试了这个实现并且它正在工作。如果您仍有问题,请告诉我。并请提供哪些不工作的细节。
    • 您好,我知道如何使用依赖服务,对于我的情况,我不需要调用 Action (_bluetoothAction)。当我这样做时,我希望看到一个弹出窗口,要求用户打开蓝牙,或者允许我的应用程序使用蓝牙。然而,这不会发生。基本上什么都没有发生。没有弹出窗口有问题或任何不确定我可能会错过什么。您是否在设备上测试过您的代码?你确定这行得通吗?
    猜你喜欢
    • 1970-01-01
    • 2020-01-27
    • 2019-12-03
    • 2012-07-17
    • 2014-02-20
    • 1970-01-01
    • 2014-07-19
    • 1970-01-01
    • 2018-09-23
    相关资源
    最近更新 更多