Search code examples
c#androidbluetoothmaui

Why MAUI DependencyService.Get Returns null?


I am trying to use Bluetooth on my phone in my MAUI App. I followed this Article. I know this might not be the best resource, but i couldn't find anything else. Did i make an error somewhere, or is this not the right strategy?

For context,I am attempting to connect to my arduino through a HC-05 module.

However when i try to use DependencyService.Get, it returns null.

Here is my Interface, located in App.xaml.cs :

namespace RobotControl
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();

            MainPage = new AppShell();
        }
    }

    public interface IBluetoothConnector
    {
        List<string> GetConnectedDevices();
        void Connect(string deviceName);

        public void Write(byte[] data);
    }
}

Here is my implementation Located in Platforms/Android/BluetoothConnector.cs:

using Android.Bluetooth;
using Java.Util;
using RobotControl.Platforms.Android.Bluetooth;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
[assembly: Dependency(typeof(RobotControl.Platforms.Android.Bluetooth.BluetoothConnector))]
namespace RobotControl.Platforms.Android.Bluetooth
{
    class BluetoothConnector : IBluetoothConnector
    {
        BluetoothAdapter adapter;
        private const string SspUuid = "00001101-0000-1000-8000-00805f9b34fb";
        private BluetoothSocket? socket;
        public void Connect(string deviceName)
        {
            var device = adapter.BondedDevices.FirstOrDefault(d=> d.Name == deviceName);
            socket = device.CreateRfcommSocketToServiceRecord(UUID.FromString(SspUuid));
            socket.Connect();
        }

        public void Write(byte[] data) 
        { 
        
        }

        public List<string> GetConnectedDevices()
        {
            adapter = BluetoothAdapter.DefaultAdapter;
            if (adapter == null) 
            {
                throw new Exception("No Bluetooth adapter");
            }

            if (adapter.IsEnabled)
            { 
                if(adapter.BondedDevices.Count >0)
                {
                    return adapter.BondedDevices.Select(x => x.Name).ToList();
                }
            }
            else
            {
                Console.WriteLine("BT is not enabled");
            }

            return new List<string>();
                
        }
    }
}

namespace RobotControl
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();

            MainPage = new AppShell();
        }
    }

    public interface IBluetoothConnector
    {
        List<string> GetConnectedDevices();
        void Connect(string deviceName);

        public void Write(byte[] data);
    }
}

Here i am trying to access the service. Lhand.xaml.cs

namespace RobotControl
{
    public partial class LHand : ContentPage
    {
        public int L_PinkyAngle;
        public int L_RingAngle;
        public int L_MiddleAngle;
        public int L_IndexAngle;
        public int L_ThumbAngle;
        public int L_RotaAngle;

        public LHand()
        {
            InitializeComponent();
        }

        private async void SPinky_ValueChanged(object sender, ValueChangedEventArgs e)
        {
            var connector = DependencyService.Get<IBluetoothConnector>();
            
            if(connector == null)
            {
                await DisplayAlert("er", "connector is null", "huh");
            }
            else
            {
                await DisplayAlert("er", "isnt null", "huh");
            }

            string x = "";
            foreach(string s in connector.GetConnectedDevices())
            {
                x += s + "\n";
            }

            await DisplayAlert("er", x+ "", "huh");
        }

        private void SRing_ValueChanged(object sender, ValueChangedEventArgs e)
        {

        }

        private void SMiddle_ValueChanged(object sender, ValueChangedEventArgs e)
        {

        }

        private void SIndex_ValueChanged(object sender, ValueChangedEventArgs e)
        {

        }

        private void SThumb_ValueChanged(object sender, ValueChangedEventArgs e)
        {

        }
    }
}

Thanks for your help.


Solution

  • You are missing the point.

    [assembly: Dependency(typeof(RobotControl.Platforms.Android.Bluetooth.BluetoothConnector))]
    

    This here, points to itself, and should point to multi-platform type.

    (Edit: I would also try manually inject it with the android type, and retrieve it with the multi-platform type.)

    Example:

    This is multi-platform code. It stays outside of platform-specific folders.

    public interface IMyInterface
    {
        string Get();
    }
    

    As you can see, it only promises that there is a method, that is called "get" and returns string. You write only this in the multi-platform part. Nothing else.


    This is platform specific code. Its location is the folder "Windows", or maybe "Android", or even "Tyzen". It is different in a way that you can call methods that are for the specific platform.

    class MyPlatformImplementation : IMyInterface
    {
        public string Get()
        {
            return "got it!";
        }
    }
    

    In your Program class, you inject the platform specific type.

    DependencyService.Register<MyPlatformImplementation>();
    

    And in your page logic, when you want to actually run this code, you do this:

    DependencyService.Get<IMyInterface>().Get();
    

    (This will return "got it!")


    This is how I would do it. And I am absolutely certain that it will work.