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:
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);
}
}
});
Check the IPAddress and ports.
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;}
}
}