Forum Xamarin.Forms

Announcement:

The Xamarin Forums have officially moved to the new Microsoft Q&A experience. Microsoft Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

To create new threads and ask questions head over to Microsoft Q&A for .NET and get involved today.

How to get the mac address of BLE device in code behind in Xamarin forms?

judsonabrahamjudsonabraham USMember ✭✭✭

I'm connecting my Bluetooth BLE device in background. So I need to get the Bluetooth mac address in my code behind just like how we are displaying the mac address in our XAML.

ListView x:Name="lv" ItemSelected="lv_ItemSelected" BackgroundColor="White" SeparatorColor="Aqua"> 
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <StackLayout>
                                <Label TextColor="Black" Text="{Binding NativeDevice.Address}"/>
                                <Label TextColor="Black" Text="{Binding NativeDevice.Name}"/>
                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>

so in our xaml I'm able to get the mac address in NativeDevice.Address. So same way I need to get it in my xaml.cs. I am able to get the mac address by following this approach

var vailditems = adapter.DiscoveredDevices.Where(i => i.NativeDevice.ToString()
But this is not good approach I need to get the mac address in NativeDevice.Address just like my xaml. I tried this approach but it is giving the address as null.

public class NativeDevice
        {

            public string Name { get; set; }
            public string Address { get; set; }
        }
NativeDevice V = new NativeDevice();

                    Baddress = V.Address;

For your information the mac address is accessible in IDevice interface which is predefined. So in the IDevice interface I need to access the object NativeDevice. This is the interface.

public interface IDevice : IDisposable
{

    Guid Id { get; }

    string Name { get; }

    int Rssi { get; }

    object NativeDevice { get; }

    DeviceState State { get; }

    IList<AdvertisementRecord> AdvertisementRecords { get; }



    Task<IService> GetServiceAsync(Guid id, CancellationToken cancellationToken = default);

    Task<IList<IService>> GetServicesAsync(CancellationToken cancellationToken = default);

    Task<bool> UpdateRssiAsync();
}

So I need to access the interface and get the NativeDevice.address in code behind.My main concern is that I'm not able to access the Address property in code behind . I'm able to access the Address property of the NativeDevice in xaml without Binding it to any model or viewmodel but I'm not able to access the Address property in code behind. And I will be removing the XAML part so I don't need the mac address from itemsource of ListView aswell. I don't have any clue regarding this. Any suggestions?

Best Answer

  • judsonabrahamjudsonabraham USMember ✭✭✭
    Accepted Answer

    For getting the address property in the code behind you need to do dependency service. So first create an interface called INativeDevice this is the code for the interface

    public interface INativeDevice
        {
            //new object NativeDevice { get; }
            //void getaddress();
            NativeDevice ConvertToNative(object device);
        }
    

    secondly create a class in android specific project called NativeDeviceConverter this is the code

    [assembly: Xamarin.Forms.Dependency(typeof(NativeDeviceConverter))]
    namespace Workshop.Droid.Injected
    {
       public class NativeDeviceConverter:INativeDevice
        {
    
            public NativeDevice ConvertToNative(object device)
            {
                var dev = device as Device;
                if (dev != null)
                    return new NativeDevice { Name = !string.IsNullOrEmpty(dev.BluetoothDevice.Name) ? dev.BluetoothDevice.Name : string.Empty, Address = dev.BluetoothDevice.Address };
                else
                    return new NativeDevice();
            }
        }
    }
    

    After this write this code in your code behind to fetch the Address of your Bluetooth device

    NativeDeviceAdd = DependencyService.Get<INativeDevice>().ConvertToNative(a.Device); PropertyInfo propInfo = NativeDeviceAdd.GetType().GetProperty("Address"); BLEaddressnew = (string)propInfo.GetValue(NativeDeviceAdd, null);
    So with this Address you can do scan operation in background and filter your discovered device.

Answers

  • jezhjezh Member, Xamarin Team Xamurai

    var vailditems = adapter.DiscoveredDevices.Where(i => i.NativeDevice.ToString()

    Since you could get the mac address by above approach,why not assign the mac address to your model, and use the data-binding method to show the mac address?

  • judsonabrahamjudsonabraham USMember ✭✭✭

    @jezh said:

    var vailditems = adapter.DiscoveredDevices.Where(i => i.NativeDevice.ToString()

    Since you could get the mac address by above approach,why not assign the mac address to your model, and use the data-binding method to show the mac address?

    I want to access the address property just like I was able to bind to my xaml from the itemsource. I want the NativeDevice.Address instead of NativeDevice.ToString(). https://github.com/didourebai/BLEPluginDemo this is the github project I'm trying to implement.

  • judsonabrahamjudsonabraham USMember ✭✭✭
    Accepted Answer

    For getting the address property in the code behind you need to do dependency service. So first create an interface called INativeDevice this is the code for the interface

    public interface INativeDevice
        {
            //new object NativeDevice { get; }
            //void getaddress();
            NativeDevice ConvertToNative(object device);
        }
    

    secondly create a class in android specific project called NativeDeviceConverter this is the code

    [assembly: Xamarin.Forms.Dependency(typeof(NativeDeviceConverter))]
    namespace Workshop.Droid.Injected
    {
       public class NativeDeviceConverter:INativeDevice
        {
    
            public NativeDevice ConvertToNative(object device)
            {
                var dev = device as Device;
                if (dev != null)
                    return new NativeDevice { Name = !string.IsNullOrEmpty(dev.BluetoothDevice.Name) ? dev.BluetoothDevice.Name : string.Empty, Address = dev.BluetoothDevice.Address };
                else
                    return new NativeDevice();
            }
        }
    }
    

    After this write this code in your code behind to fetch the Address of your Bluetooth device

    NativeDeviceAdd = DependencyService.Get<INativeDevice>().ConvertToNative(a.Device); PropertyInfo propInfo = NativeDeviceAdd.GetType().GetProperty("Address"); BLEaddressnew = (string)propInfo.GetValue(NativeDeviceAdd, null);
    So with this Address you can do scan operation in background and filter your discovered device.

  • dlchambersdlchambers Member ✭✭

    I get "The type or namespace name 'NativeDeviceConverter' could not be found."
    Same error on NativeDevice.
    What reference/using/attribute am I missing?

  • judsonabrahamjudsonabraham USMember ✭✭✭
    edited January 21

    @dlchambers what I'm doing is a dependency service. So NativeDeviceConverter is the name of class which will be in android and iOS specific project. And the NativeDevice is a method which returns the device name and adddress. For more info check out this link

    https://stackoverflow.com/questions/64612173/how-to-get-the-mac-address-of-ble-device-in-code-behind-in-xamarin-forms

    and also look into implementing dependency service in Xamarin forms.

  • dlchambersdlchambers Member ✭✭

    Sorry for being slow on this :) but I'm getting two errors in in ConvertToNative():
    1) var dev = device as Device;
    Error: Cannot declare a variable of static type 'Device'
    2) 'dev' does not contain 'BluetoothDevice' (e.g. in dev.BluetoothDevice.Name).
    Any ideas?
    Thanks!

  • dlchambersdlchambers Member ✭✭

    Update:
    This works:
    Plugin.BLE.Android.Device dev = device as Plugin.BLE.Android.Device;
    instead of:
    var dev = device as Device;

  • judsonabrahamjudsonabraham USMember ✭✭✭

    @dlchambers you can avoid Plugin.BLE.Android if you are installing Plugin.BLE from manage nuget . And after installing the nuget package you can directly use namespace.

  • dlchambersdlchambers Member ✭✭

    @judsonabraham Understood, did use nuget;
    I just included the namespace in the code for clarity.
    My previous "Cannot declare a variable" issue was caused by not including "using Plugin.BLE.Android;"
    In the end, I left the namespaces in the code to eliminate ambiguity.

  • judsonabrahamjudsonabraham USMember ✭✭✭
    edited January 23

    @dlchambers glad that it worked for you. Happy coding :)

Sign In or Register to comment.