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);
}
}
});
CodePudding user response:
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;} } }