翼度科技»论坛 编程开发 .net 查看内容

bh003- Blazor hybrid / Maui 使用蓝牙BLE快速教程

3

主题

3

帖子

9

积分

新手上路

Rank: 1

积分
9
1. 建立工程 bh003_ble

源码
2. 添加 nuget 包
  1. [/code]BlazorHybrid.Maui.Permissions 因为源码比较长,主要是一些检查和申请权限,BLE权限相关代码,就不占用篇幅列出,感兴趣的同学直接打开[url=https://github.com/densen2014/BlazorHybrid/tree/master/BlazorHybrid.Maui.Permissions?WT.mc_id=DT-MVP-5005078]源码[/url]参考
  2. 顺便打开可空 enable
  3. [size=4]3. 添加蓝牙权限[/size]
  4. [size=3]安卓[/size]
  5. AndroidManifest.xml
  6. [code]<?xml version="1.0" encoding="utf-8"?>
  7. <manifest xmlns:android="http://schemas.android.com/apk/res/android">
  8.   <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
  9.   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  10.   <uses-permission android:name="android.permission.INTERNET" />
  11.   
  12.   <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
  13.   
  14.   <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  15.   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  16.   <uses-permission android:name="android.permission.BLUETOOTH"/>
  17.   <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
  18.   
  19.   
  20.   
  21.   
  22.   <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/>
  23.   <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
  24.   
  25. </manifest>
复制代码
iOS

Info.plist
  1.     <key>UIBackgroundModes</key>
  2.     <array>
  3.         <string>bluetooth-central</string>
  4.         <string>bluetooth-peripheral</string>
  5.     </array>
  6.     <key>NSBluetoothPeripheralUsageDescription</key>
  7.     <string>此应用程序需要访问您的蓝牙。请根据要求授予权限.</string>
  8.     <key>NSBluetoothAlwaysUsageDescription</key>
  9.     <string>此应用程序需要访问您的蓝牙。请根据要求授予权限.</string>
复制代码
以下是完整文件
  1.     LSRequiresIPhoneOS        UIDeviceFamily            1        2        UIRequiredDeviceCapabilities            arm64        UISupportedInterfaceOrientations            UIInterfaceOrientationPortrait        UIInterfaceOrientationLandscapeLeft        UIInterfaceOrientationLandscapeRight        UISupportedInterfaceOrientations~ipad            UIInterfaceOrientationPortrait        UIInterfaceOrientationPortraitUpsideDown        UIInterfaceOrientationLandscapeLeft        UIInterfaceOrientationLandscapeRight        XSAppIconAssets    Assets.xcassets/appicon.appiconset    <key>UIBackgroundModes</key>
  2.     <array>
  3.         <string>bluetooth-central</string>
  4.         <string>bluetooth-peripheral</string>
  5.     </array>
  6.     <key>NSBluetoothPeripheralUsageDescription</key>
  7.     <string>此应用程序需要访问您的蓝牙。请根据要求授予权限.</string>
  8.     <key>NSBluetoothAlwaysUsageDescription</key>
  9.     <string>此应用程序需要访问您的蓝牙。请根据要求授予权限.</string>
复制代码
Windows

Package.appxmanifest

4. 编辑 Index.html 文件,引用 BootstrapBlazor UI 库.

完整文件
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="utf-8" />
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
  6.     <title>bh003_ble</title>
  7.     <base href="/" />
  8.     <link href="_content/BootstrapBlazor.FontAwesome/css/font-awesome.min.css" rel="stylesheet">
  9.     <link href="_content/BootstrapBlazor/css/bootstrap.blazor.bundle.min.css" rel="stylesheet">
  10.     <link href="_content/BootstrapBlazor/css/motronic.min.css" rel="stylesheet">
  11.     <link href="css/app.css" rel="stylesheet" />
  12.     <link href="bh003_ble.styles.css" rel="stylesheet" />
  13. </head>
  14. <body>
  15.    
  16.     Loading...
  17.    
  18.         An unhandled error has occurred.
  19.         <a target="_blank" href="https://www.cnblogs.com/" >Reload</a>
  20.         <a ><i ></i></a>
  21.    
  22.    
  23.    
  24. </body>
  25. </html>
复制代码

5. 添加 BootstrapBlazorRoot 组件

Main.razor 文件添加 BootstrapBlazorRoot 组件

6. 添加命名空间引用

_Imports.razor
  1. @using BootstrapBlazor.Components
复制代码
7. 添加服务

MauiProgram.cs
添加
  1.             builder.Services.AddDensenExtensions();
  2.             builder.Services.ConfigureJsonLocalizationOptions(op =>
  3.             {
  4.                 // 忽略文化信息丢失日志
  5.                 op.IgnoreLocalizerMissing = true;
  6.             });
  7.             builder.Services.AddSingleton<BluetoothLEServices>();
  8.             builder.Services.AddScoped<IStorage, StorageService>();
复制代码
完整文件
  1. using bh003_ble.Data;using Microsoft.Extensions.Logging;using BlazorHybrid.Maui.Shared;using BootstrapBlazor.WebAPI.Services;namespace bh003_ble{    public static class MauiProgram    {        public static MauiApp CreateMauiApp()        {            var builder = MauiApp.CreateBuilder();            builder                .UseMauiApp()                .ConfigureFonts(fonts =>                {                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");                });            builder.Services.AddMauiBlazorWebView();#if DEBUG                builder.Services.AddBlazorWebViewDeveloperTools();                builder.Logging.AddDebug();#endif            builder.Services.AddSingleton();            builder.Services.AddDensenExtensions();
  2.             builder.Services.ConfigureJsonLocalizationOptions(op =>
  3.             {
  4.                 // 忽略文化信息丢失日志
  5.                 op.IgnoreLocalizerMissing = true;
  6.             });
  7.             builder.Services.AddSingleton<BluetoothLEServices>();
  8.             builder.Services.AddScoped<IStorage, StorageService>();            return builder.Build();        }    }}
复制代码
8. 添加代码后置文件 Pages/Index.razor.cs

Index.razor.cs
  1. using BlazorHybrid.Core.Device;
  2. using BlazorHybrid.Maui.Shared;
  3. using BootstrapBlazor.Components;
  4. using BootstrapBlazor.WebAPI.Services;
  5. using Microsoft.AspNetCore.Components;
  6. using System.Diagnostics.CodeAnalysis;
  7. namespace bh003_ble.Pages;
  8. public partial class Index : IAsyncDisposable
  9. {
  10.     [Inject, NotNull]
  11.     BluetoothLEServices? MyBleTester { get; set; }
  12.     [Inject, NotNull] protected IStorage? Storage { get; set; }
  13.     [Inject, NotNull] protected ToastService? ToastService { get; set; }
  14.     public void SetTagDeviceName(BleTagDevice ble)
  15.     {
  16.         MyBleTester.TagDevice = ble;
  17.         if (!isInit)
  18.         {
  19.             MyBleTester.OnMessage += OnMessage;
  20.             MyBleTester.OnDataReceived += OnDataReceived;
  21.             MyBleTester.OnStateConnect += OnStateConnect;
  22.             isInit = true;
  23.         }
  24.     }
  25.     public event Action<string>? OnMessage;
  26.     public event Action<string>? OnDataReceived;
  27.     public event Action<bool>? OnStateConnect;
  28.     bool isInit = false;
  29.     public async Task<List<BleDevice>?> StartScanAsync() => await MyBleTester.StartScanAsync();
  30.     public async Task<List<BleService>?> ConnectToKnownDeviceAsync(Guid deviceID, string? deviceName = null) => await MyBleTester.ConnectToKnownDeviceAsync(deviceID, deviceName);
  31.     public async Task<List<BleCharacteristic>?> GetCharacteristicsAsync(Guid serviceid) => await MyBleTester.GetCharacteristicsAsync(serviceid);
  32.     public async Task<string?> ReadDeviceName(Guid? serviceid, Guid? characteristic) => await MyBleTester.ReadDeviceName(serviceid, characteristic);
  33.     public async Task<byte[]?> ReadDataAsync(Guid characteristic) => await MyBleTester.ReadDataAsync(characteristic);
  34.     public async Task<bool> SendDataAsync(Guid characteristic, byte[] ary) => await MyBleTester.SendDataAsync(characteristic, ary);
  35.     public async Task<bool> DisConnectDeviceAsync() => await MyBleTester.DisConnectDeviceAsync();
  36.     public Task<bool> BluetoothIsBusy() => MyBleTester.BluetoothIsBusy();
  37.     private bool IsScanning = false;
  38.     private List<BleDevice>? Devices { get; set; }
  39.     private List<BleService>? Services { get; set; }
  40.     private List<BleCharacteristic>? Characteristics { get; set; }
  41.     private string? ReadResult { get; set; }
  42.     private string? Message { get; set; } = "";
  43.     BleTagDevice BleInfo { get; set; } = new BleTagDevice();
  44.     private List<SelectedItem> DemoList { get; set; } = new List<SelectedItem>() { new SelectedItem() { Text = "测试数据", Value = "" } };
  45.     private List<SelectedItem> DeviceList { get; set; } = new List<SelectedItem>();
  46.     private List<SelectedItem> ServiceidList { get; set; } = new List<SelectedItem>();
  47.     private List<SelectedItem> CharacteristicList { get; set; } = new List<SelectedItem>();
  48.     private Dictionary<string, object>? IsScanningCss => IsScanning ? new() { { "disabled", "" }, } : null;
  49.     bool IsAutoConnect { get; set; }
  50.     bool IsAuto { get; set; }
  51.     bool IsInit { get; set; }
  52.     protected override async Task OnAfterRenderAsync(bool firstRender)
  53.     {
  54.         if (firstRender)
  55.         {
  56.             await Init();
  57.         }
  58.     }
  59.     async Task<bool> Init()
  60.     {
  61.         try
  62.         {
  63.             if (IsInit) return true;
  64.             if (await BluetoothIsBusy())
  65.             {
  66.                 await ToastService.Warning("蓝牙正在使用中,请稍后再试");
  67.                 return false;
  68.             }
  69.             OnMessage += Tools_OnMessage;
  70.             OnDataReceived += Tools_OnDataReceived;
  71.             OnStateConnect += Tools_OnStateConnect;
  72.             SetTagDeviceName(BleInfo);
  73.             IsInit = true;
  74.             StateHasChanged();
  75.             var deviceID = await Storage.GetValue("bleDeviceID", string.Empty);
  76.             if (!string.IsNullOrEmpty(deviceID))
  77.             {
  78.                 BleInfo.Name = await Storage.GetValue("bleDeviceName", string.Empty);
  79.                 BleInfo.DeviceID = Guid.Parse(deviceID);
  80.                 var serviceid = await Storage.GetValue("bleServiceid", string.Empty);
  81.                 if (!string.IsNullOrEmpty(serviceid)) BleInfo.Serviceid = Guid.Parse(serviceid);
  82.                 var characteristic = await Storage.GetValue("bleCharacteristic", string.Empty);
  83.                 if (!string.IsNullOrEmpty(characteristic)) BleInfo.Characteristic = Guid.Parse(characteristic);
  84.                 var auto = await Storage.GetValue("bleAutoConnect", string.Empty);
  85.                 if (auto == "True")
  86.                 {
  87.                     IsAuto = true;
  88.                     await AutoRead();
  89.                 }
  90.             }
  91.             return true;
  92.         }
  93.         catch (Exception ex)
  94.         {
  95.             System.Console.WriteLine(ex.Message);
  96.         }
  97.         return false;
  98.     }
  99.     private async Task AutoRead()
  100.     {
  101.         Services = null;
  102.         Characteristics = null;
  103.         Message = "";
  104.         ReadResult = "";
  105.         Devices = new List<BleDevice>() { new BleDevice() { Id = BleInfo.DeviceID, Name = BleInfo.Name } };
  106.         DeviceList = new List<SelectedItem>() { new SelectedItem() { Text = BleInfo.Name, Value = BleInfo.DeviceID.ToString() } };
  107.         IsAutoConnect = true;
  108.         await OnDeviceSelect();
  109.         IsAutoConnect = false;
  110.     }
  111.     private async Task OnStateChanged(bool value)
  112.     {
  113.         await Storage.SetValue("bleAutoConnect", value.ToString());
  114.     }
  115.     private void Tools_OnStateConnect(bool obj)
  116.     {
  117.     }
  118.     private async void Tools_OnDataReceived(string message)
  119.     {
  120.         ReadResult = message;
  121.         Tools_OnMessage(message);
  122.         await InvokeAsync(StateHasChanged);
  123.     }
  124.     private async void Tools_OnMessage(string message)
  125.     {
  126.         if (Message != null && Message.Length > 500) Message = Message.Substring(0, 500);
  127.         Message = $"{message}\r\n{Message}";
  128.         await InvokeAsync(StateHasChanged);
  129.     }
  130.     //扫描外设
  131.     private async void ScanDevice()
  132.     {
  133.         if (!await Init()) return;
  134.         IsScanning = true;
  135.         Devices = null;
  136.         Services = null;
  137.         Characteristics = null;
  138.         Message = "";
  139.         ReadResult = "";
  140.         DeviceList = new List<SelectedItem>() { new SelectedItem() { Text = "请选择...", Value = "" } };
  141.         //开始扫描
  142.         Devices = await StartScanAsync();
  143.         if (Devices != null)
  144.         {
  145.             Devices.ForEach(a => DeviceList.Add(new SelectedItem() { Active = IsAutoConnect && a.Id == BleInfo.DeviceID, Text = a.Name ?? a.Id.ToString(), Value = a.Id.ToString() }));
  146.         }
  147.         IsScanning = false;
  148.         //异步更新UI
  149.         await InvokeAsync(StateHasChanged);
  150.     }
  151.     //连接外设
  152.     private async Task OnDeviceSelect(SelectedItem item)
  153.     {
  154.         if (IsAutoConnect || item.Value == "") return;
  155.         BleInfo.Name = item.Text;
  156.         BleInfo.DeviceID = Guid.Parse(item.Value);
  157.         await OnDeviceSelect();
  158.     }
  159.     private async Task OnDisConnectDevice()
  160.     {
  161.         if (await DisConnectDeviceAsync())
  162.             await ToastService.Success("断开成功");
  163.         else
  164.             await ToastService.Error("断开失败");
  165.     }
  166.     private async Task OnDeviceSelect()
  167.     {
  168.         Services = null;
  169.         Characteristics = null;
  170.         Message = "";
  171.         ReadResult = "";
  172.         ServiceidList = new List<SelectedItem>() { new SelectedItem() { Text = "请选择...", Value = "" } };
  173.         //连接外设
  174.         Services = await ConnectToKnownDeviceAsync(BleInfo.DeviceID, BleInfo.Name);
  175.         if (Services != null)
  176.         {
  177.             Services.ForEach(a => ServiceidList.Add(new SelectedItem() { Active = IsAutoConnect && a.Id == BleInfo.Serviceid, Text = a.Name ?? a.Id.ToString(), Value = a.Id.ToString() }));
  178.             await Storage.SetValue("bleDeviceID", BleInfo.DeviceID.ToString());
  179.             await Storage.SetValue("bleDeviceName", BleInfo.Name ?? "上次设备");
  180.             if (BleInfo.Serviceid != Guid.Empty && IsAutoConnect)
  181.             {
  182.                 await OnServiceidSelect();
  183.             }
  184.         }
  185.         //异步更新UI
  186.         await InvokeAsync(StateHasChanged);
  187.     }
  188.     private async Task OnServiceidSelect(SelectedItem item)
  189.     {
  190.         if (IsAutoConnect || item.Value == "") return;
  191.         BleInfo.Serviceid = Guid.Parse(item.Value);
  192.         await OnServiceidSelect();
  193.     }
  194.     private async Task OnServiceidSelect()
  195.     {
  196.         Characteristics = null;
  197.         Message = "";
  198.         ReadResult = "";
  199.         CharacteristicList = new List<SelectedItem>() { new SelectedItem() { Text = "请选择...", Value = "" } };
  200.         Characteristics = await GetCharacteristicsAsync(BleInfo.Serviceid);
  201.         if (Characteristics != null)
  202.         {
  203.             Characteristics.ForEach(a => CharacteristicList.Add(new SelectedItem() { Active = IsAutoConnect && a.Id == BleInfo.Characteristic, Text = a.Name ?? a.Id.ToString(), Value = a.Id.ToString() }));
  204.             await Storage.SetValue("bleServiceid", BleInfo.Serviceid.ToString());
  205.             if (BleInfo.Characteristic != Guid.Empty && IsAutoConnect)
  206.             {
  207.                 await ReadDeviceName();
  208.             }
  209.         }
  210.         await InvokeAsync(StateHasChanged);
  211.     }
  212.     private async Task OnCharacteristSelect(SelectedItem item)
  213.     {
  214.         if (IsAutoConnect) return;
  215.         BleInfo.Characteristic = Guid.Parse(item.Value);
  216.         await ReadDeviceName();
  217.     }
  218.     //读取数值
  219.     private async Task ReadDeviceName()
  220.     {
  221.         Message = "";
  222.         //读取数值
  223.         ReadResult = await ReadDeviceName(BleInfo.Serviceid, BleInfo.Characteristic);
  224.         await Storage.SetValue("bleCharacteristic", BleInfo.Characteristic.ToString());
  225.         if (!string.IsNullOrEmpty(ReadResult)) await ToastService.Information("读取成功", ReadResult);
  226.         //异步更新UI
  227.         await InvokeAsync(StateHasChanged);
  228.     }
  229.     private async Task ReadDataAsync()
  230.     {
  231.         Message = "";
  232.         //读取数值
  233.         var res = await ReadDataAsync(BleInfo.Characteristic);
  234.         if (!string.IsNullOrEmpty(ReadResult)) await ToastService.Information("读取成功", res.ToString());
  235.         //异步更新UI
  236.         await InvokeAsync(StateHasChanged);
  237.     }
  238.     private async Task SendDataAsync()
  239.     {
  240.         Message = "";
  241.         //读取数值
  242.         var res = await SendDataAsync(BleInfo.Characteristic, null);
  243.         await ToastService.Information("成功发送", res.ToString());
  244.         //异步更新UI
  245.         await InvokeAsync(StateHasChanged);
  246.     }
  247.     ValueTask IAsyncDisposable.DisposeAsync()
  248.     {
  249.         OnMessage -= Tools_OnMessage;
  250.         OnDataReceived -= Tools_OnDataReceived;
  251.         OnStateConnect -= Tools_OnStateConnect;
  252.         return new ValueTask();
  253.     }
  254. }
复制代码
9. 添加 UI Pages/Index.razor

Index.razor
  1. @page "/"[size=4]蓝牙[/size]
  2.                     @if (Devices != null)        {<?xml version="1.0" encoding="utf-8"?>
  3. <manifest xmlns:android="http://schemas.android.com/apk/res/android">
  4.   <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
  5.   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  6.   <uses-permission android:name="android.permission.INTERNET" />
  7.   
  8.   <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
  9.   
  10.   <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  11.   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  12.   <uses-permission android:name="android.permission.BLUETOOTH"/>
  13.   <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
  14.   
  15.   
  16.   
  17.   
  18.   <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/>
  19.   <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
  20.   
  21. </manifest>  @if (Characteristics != null)            {<?xml version="1.0" encoding="utf-8"?>
  22. <manifest xmlns:android="http://schemas.android.com/apk/res/android">
  23.   <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
  24.   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  25.   <uses-permission android:name="android.permission.INTERNET" />
  26.   
  27.   <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
  28.   
  29.   <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  30.   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  31.   <uses-permission android:name="android.permission.BLUETOOTH"/>
  32.   <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
  33.   
  34.   
  35.   
  36.   
  37.   <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/>
  38.   <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
  39.   
  40. </manifest>          }        }    @if (Devices != null){<?xml version="1.0" encoding="utf-8"?>
  41. <manifest xmlns:android="http://schemas.android.com/apk/res/android">
  42.   <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
  43.   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  44.   <uses-permission android:name="android.permission.INTERNET" />
  45.   
  46.   <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
  47.   
  48.   <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  49.   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  50.   <uses-permission android:name="android.permission.BLUETOOTH"/>
  51.   <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
  52.   
  53.   
  54.   
  55.   
  56.   <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/>
  57.   <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
  58.   
  59. </manifest>      @if (Services != null)        {<?xml version="1.0" encoding="utf-8"?>
  60. <manifest xmlns:android="http://schemas.android.com/apk/res/android">
  61.   <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
  62.   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  63.   <uses-permission android:name="android.permission.INTERNET" />
  64.   
  65.   <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
  66.   
  67.   <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  68.   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  69.   <uses-permission android:name="android.permission.BLUETOOTH"/>
  70.   <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
  71.   
  72.   
  73.   
  74.   
  75.   <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/>
  76.   <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
  77.   
  78. </manifest>                  @if (Characteristics != null)            {<?xml version="1.0" encoding="utf-8"?>
  79. <manifest xmlns:android="http://schemas.android.com/apk/res/android">
  80.   <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
  81.   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  82.   <uses-permission android:name="android.permission.INTERNET" />
  83.   
  84.   <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
  85.   
  86.   <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  87.   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  88.   <uses-permission android:name="android.permission.BLUETOOTH"/>
  89.   <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
  90.   
  91.   
  92.   
  93.   
  94.   <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/>
  95.   <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
  96.   
  97. </manifest><?xml version="1.0" encoding="utf-8"?>
  98. <manifest xmlns:android="http://schemas.android.com/apk/res/android">
  99.   <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
  100.   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  101.   <uses-permission android:name="android.permission.INTERNET" />
  102.   
  103.   <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
  104.   
  105.   <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  106.   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  107.   <uses-permission android:name="android.permission.BLUETOOTH"/>
  108.   <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
  109.   
  110.   
  111.   
  112.   
  113.   <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/>
  114.   <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
  115.   
  116. </manifest>@if (ReadResult != null)                {<?xml version="1.0" encoding="utf-8"?>
  117. <manifest xmlns:android="http://schemas.android.com/apk/res/android">
  118.   <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
  119.   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  120.   <uses-permission android:name="android.permission.INTERNET" />
  121.   
  122.   <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
  123.   
  124.   <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  125.   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  126.   <uses-permission android:name="android.permission.BLUETOOTH"/>
  127.   <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
  128.   
  129.   
  130.   
  131.   
  132.   <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/>
  133.   <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
  134.   
  135. </manifest><?xml version="1.0" encoding="utf-8"?>
  136. <manifest xmlns:android="http://schemas.android.com/apk/res/android">
  137.   <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
  138.   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  139.   <uses-permission android:name="android.permission.INTERNET" />
  140.   
  141.   <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
  142.   
  143.   <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  144.   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  145.   <uses-permission android:name="android.permission.BLUETOOTH"/>
  146.   <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
  147.   
  148.   
  149.   
  150.   
  151.   <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/>
  152.   <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
  153.   
  154. </manifest>            }            }        }    }@if (BleInfo.Name != null){            历史连接
  155.         @BleInfo.Name
  156.         @BleInfo.DeviceID
  157.         @BleInfo.Serviceid
  158.         @BleInfo.Characteristic
  159.         @ReadResult
  160.     }@Message
复制代码
10. 运行




11. 相关资料

如何远程调试 MAUI blazor / Blazor Hybrid
https://www.cnblogs.com/densen2014/p/16988516.html

来源:https://www.cnblogs.com/densen2014/archive/2023/08/23/17649961.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具