Search code examples
c#xamarinxamarin.formsxamarin.androidmulticast

Xamarin MulticastLock Acquiring doesn't allow multicast


I am using Xamarin to create an Android application. This app must, among other things, receive a multicast stream. The server is sending fine, but my app is not receiving properly. If I acquire the multicast lock, which is what my research seems say is all I need to do, I can see I have the lock, but the app still does not receive the data.

var wifiManager = var wifiManager = (WifiManager)Application.Context.GetSystemService(Context.WifiService);
// Acquire the lock
if (wifiManager != null)
{
    // _lock is a private member WifiManager.MulticastLock _lock
    _lock = wifiManager.CreateMulticastLock("PiEar");

    if (_lock != null)
    {
        _lock.Acquire();
    } 
    else
    {
        Debug.WriteLine("Could not acquire multicast lock"); // Does not print, meaning I do acquire the lock (and _lock.IsHeld() returns true)
    }
} 
else 
{
    Debug.WriteLine("WifiManager is null"); // Does not print, meaning it is not null
}

If I then use a different app, MSniffer, it not only receives the data, but allows my app to do so as well. Am I doing something wrong with attempting to acquire the lock?

Also, I have the following permissions:

  • ACCESS_WIFI_STATE
  • CHANGE_WIFI_STATE
  • ACCESS_NETWORK_STATE
  • INTERNET
  • CHANGE_WIFI_MULTICAST_STATE

Edit 1: More info

The .cs page's code in question is below. _receivedMessages is a ListView, allowing me to visually see received data. The above code is what is run on line 2 below. The only code in the dependency service is the code acquiring the lock.

var service = DependencyService.Get<IMulticastLock>();
service.Acquire();
Task.Run(async () =>
{
    while (true)
    {
        try
        {
            var endpoint = new IPEndPoint(IPAddress.Parse("224.0.0.69"), 6666);
            var multicast = new UdpClient(endpoint);
            while (true)
            {

                var multicastBytes = await multicast.ReceiveAsync();
                var message = Encoding.UTF8.GetString(multicastBytes.Buffer);
                Debug.WriteLine($"Received: {message}");
                Device.BeginInvokeOnMainThread(() =>
                {
                    _receivedMessages.Add(message);
                });
            }
        }
        catch (Exception e)
        {
            Debug.WriteLine(e);
        }
    }
});

Solution

    1. Check the IPAddress and ports.

    2. You could try to use the code below about how to create and configure UdpClient.

      public class MulticastUdpClient
      {
       UdpClient _udpclient;
       int _port;
       IPAddress _multicastIPaddress;
       IPAddress _localIPaddress;
       IPEndPoint _localEndPoint;
       IPEndPoint _remoteEndPoint;
      
       public MulticastUdpClient(IPAddress multicastIPaddress, int port, IPAddress localIPaddress = null)
       {
           // Store params
           _multicastIPaddress = multicastIPaddress;
           _port = port;
           _localIPaddress = localIPaddress;
           if (localIPaddress == null)
               _localIPaddress = IPAddress.Any;
      
           // Create endpoints
           _remoteEndPoint = new IPEndPoint(_multicastIPaddress, port);
           _localEndPoint = new IPEndPoint(_localIPaddress, port);
      
           // Create and configure UdpClient
           _udpclient = new UdpClient();
           // The following three lines allow multiple clients on the same PC
           _udpclient.ExclusiveAddressUse = false;
           _udpclient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
           _udpclient.ExclusiveAddressUse = false;
           // Bind, Join
           _udpclient.Client.Bind(_localEndPoint);
           _udpclient.JoinMulticastGroup(_multicastIPaddress, _localIPaddress);
      
           // Start listening for incoming data
           _udpclient.BeginReceive(new AsyncCallback(ReceivedCallback), null);
       }
      
       /// <summary>
       /// Send the buffer by UDP to multicast address
       /// </summary>
       /// <param name="bufferToSend"></param>
       public void SendMulticast(byte[] bufferToSend)
       {
           _udpclient.Send(bufferToSend, bufferToSend.Length, _remoteEndPoint);
       }
      
       /// <summary>
       /// Callback which is called when UDP packet is received
       /// </summary>
       /// <param name="ar"></param>
       private void ReceivedCallback(IAsyncResult ar)
       {
           // Get received data
           IPEndPoint sender = new IPEndPoint(0, 0);
           Byte[] receivedBytes = _udpclient.EndReceive(ar, ref sender);
      
           // fire event if defined
           if (UdpMessageReceived != null)
               UdpMessageReceived(this, new UdpMessageReceivedEventArgs() { Buffer = receivedBytes });
      
           // Restart listening for udp data packages
           _udpclient.BeginReceive(new AsyncCallback(ReceivedCallback), null);
       }
      
       /// <summary>
       /// Event handler which will be invoked when UDP message is received
       /// </summary>
       public event EventHandler<UdpMessageReceivedEventArgs> UdpMessageReceived;
      
       /// <summary>
       /// Arguments for UdpMessageReceived event handler
       /// </summary>
       public class UdpMessageReceivedEventArgs: EventArgs
       {
           public byte[] Buffer {get;set;}
       }
      
      }