.netbluetoothbluetooth-lowenergymauimobile-application

Plugin BLE showing unhandled exception .NET MAUI


I am trying to develop an app for connecting devices using Bluetooth , I am using Plugin.BLE for that purpose, but it is showing some unhandled exception

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application android:allowBackup="true" android:supportsRtl="true"></application>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

</manifest>

scanPage.xaml.cs

using Plugin.BLE;
using Plugin.BLE.Abstractions;
using Plugin.BLE.Abstractions.Contracts;
using Plugin.BLE.Abstractions.EventArgs;
using Plugin.BLE.Abstractions.Extensions;
using System;
using System.Text;
using System.Threading;


namespace sampleApp;

public partial class scanPage : ContentPage
{

    private CancellationToken cancellationToken;
    public scanPage()
    {
        InitializeComponent();
   
    }


    private async void scanBtn_Clicked(object sender, EventArgs e)
    {
        var adapter = CrossBluetoothLE.Current.Adapter;
        var systemDevices = adapter.GetSystemConnectedOrPairedDevices();

        var filteredDevices = systemDevices.Where(device => device.Name != null).ToList();

        ScanFilterOptions filterOptions = new ScanFilterOptions();
        // Create a list to hold device names for display
        var deviceList = filteredDevices.Select(device => device.Name);
        var deviceNames = deviceList.ToList();

        var device = systemDevices[0];
        try
        {
           Guid service_id = filterOptions.ServiceUuids[0];
                                
           Guid serviceUUID = service_id;

            var charUUID = Guid.Parse("00002A00-0000-1000-8000-00805f9b34fb");
            await adapter.ConnectToKnownDeviceAsync(serviceUUID);

            await SendDataToDevice(device, serviceUUID, charUUID);

            await DisplayAlert("Success", $"Connected to {device}!", "Ok");
        }
        catch (Exception ex)
        {
            await DisplayAlert("Exception", $"{ex.Message}", "Ok");
        }
    }
    private async Task SendDataToDevice(IDevice device, object serviceUuid, object characteristicUuid)
    {
        try
        {
            // Get the service and characteristic
            var service = await device.GetServiceAsync((Guid)serviceUuid);
            var characteristic = await service.GetCharacteristicAsync((Guid)characteristicUuid);

            // Your message to send
            string message = "Hello World from Xamarin.Forms!";

            // Convert message to byte array (replace with your encoding if needed)
            byte[] messageBuffer = Encoding.ASCII.GetBytes(message);

            // Write data to the characteristic
            await characteristic.WriteAsync(messageBuffer);

            await DisplayAlert("Sent", "Message sent successfully!", "Ok");
        }
        catch (Exception ex)
        {
            await DisplayAlert("Error", ex.Message, "Ok");
        }
    }
    private async void ListDataItem(object sender, SelectedItemChangedEventArgs e)
    {
        if (e.SelectedItem == null)
        {
            return; // No item selected, ignore
        }
        var selectedDeviceName = e.SelectedItem.ToString();

        // Handle device selection here (e.g., display alert or perform an action)
        await DisplayAlert("Selected Device", $"You selected: {selectedDeviceName}", "Ok");
    }
}

scanPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="sampleApp.scanPage"
             Title="scanPage">
    <VerticalStackLayout HorizontalOptions="Center" VerticalOptions="Center" Spacing="50">
        <Label 
            Text="Welcome to .NET MAUI!"
            VerticalOptions="Center" 
            HorizontalOptions="Center" />

        <Button x:Name="scanBtn" Text="Scan now" Clicked="scanBtn_Clicked"/>
    </VerticalStackLayout>
</ContentPage>

I am encountering the following exception

Java.Lang.SecurityException: 'Need android.permission.BLUETOOTH_CONNECT permission for android.content.AttributionSource@c82fb2a4: GattService getDevicesMatchingConnectionStates'

I have added the particular dependency as well still I am getting this exception.

Help appreciated!


Solution

  • Java.Lang.SecurityException: 'Need android.permission.BLUETOOTH_CONNECT permission for android.content.AttributionSource@c82fb2a4: GattService getDevicesMatchingConnectionStates'

    Since Android 6.0 not every permission is granted just because its placed in manifest. We need to handle runtime permission at runtime. For how to request runtime permissions, you can check: Request runtime permissions.

    And from document Bluetooth LE plugin for Xamarin & MAUI,we could find that:

    Android 12 and above may require one or more of the following additional runtime permissions depending on which features of the library you are using (see the android Bluetooth permissions documentation)

    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
    

    Note:

    On Maui, you can use Permissions to check and request runtime permission.