How to broadcast a UDP packet from Android?
Asked Answered
H

2

5

I need to broadcast a message using UDP from my Android app to every device on my network (ethernet). I'm lost on how to do this though because there doesn't seem to be any documentation on how to send a broadcast message, just ones on how to send to a specific client using IP addresses.

Thanks

Homeo answered 23/9, 2020 at 15:10 Comment(2)
Use the broadcast IP address. Remember that broadcasts do not cross routers, so you can only broadcast on the network to which you are connected.Disillusionize
There is a single broadcast address that can be used: the Limited Broadcast address of 255.255.255.255. It works on every IPv4 network, and there is no real reason to spend a lot of cycles calculating the network broadcast address. Of course, broadcasting only works for IPv4 because IPv6 has eliminated broadcast because it is intrusive, interrupting every host on the LAN, and it is a security problem. The modern method is multicast.Disillusionize
C
6

Here is a useful doc: google-AdroidUDP, and here is a sample code:

Sender:

 public void sendBroadcast(String messageStr) {
     StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);

     try {
         DatagramSocket socket = new DatagramSocket();
         socket.setBroadcast(true);
         byte[] sendData = messageStr.getBytes();
         DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, getBroadcastAddress(), Constants.PORT);
         socket.send(sendPacket);
         System.out.println(getClass().getName() + "Broadcast packet sent to: " + getBroadcastAddress().getHostAddress());
     } catch (IOException e) {
         Log.e(TAG, "IOException: " + e.getMessage());
     }
 }
 
 InetAddress getBroadcastAddress() throws IOException {
     WifiManager wifi = (WifiManager)    
     mContext.getSystemService(Context.WIFI_SERVICE);
     DhcpInfo dhcp = wifi.getDhcpInfo();


     int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask;
     byte[] quads = new byte[4];
     for (int k = 0; k < 4; k++)
         quads[k] = (byte) ((broadcast >> k * 8) & 0xFF);
     return InetAddress.getByAddress(quads);
 }

Receiver

      try {
          socket = new DatagramSocket(Constants.PORT, InetAddress.getByName("0.0.0.0"));
          socket.setBroadcast(true);

          while (true) {
              Log.i(TAG,"Ready to receive broadcast packets!");

              byte[] recvBuf = new byte[15000];
              DatagramPacket packet = new DatagramPacket(recvBuf, recvBuf.length);
              socket.receive(packet);

              Log.i(TAG, "Packet received from: " + packet.getAddress().getHostAddress());
              String data = new String(packet.getData()).trim();
              Log.i(TAG, "Packet received; data: " + data);

              Intent localIntent = new Intent(Constants.BROADCAST_ACTION)
                  .putExtra(Constants.EXTENDED_DATA_STATUS, data);
              LocalBroadcastManager
                  .getInstance(this)
                  .sendBroadcast(localIntent);
          }
      }  catch (IOException ex) {
          Log.i(TAG, "Oops" + ex.getMessage());
      }
Compartment answered 23/9, 2020 at 17:20 Comment(5)
Hmm this includes "wifi manager" is this possible to do over ethernet?Homeo
There is a single broadcast address that can be used: the Limited Broadcast address of 255.255.255.255. It works on every IPv4 network, and there is no real reason to spend a lot of cycles calculating the network broadcast address. Of course, broadcasting only works for IPv4 because IPv6 has eliminated broadcast because it is intrusive, interrupting every host on the LAN, and it is a security problem. The modern method is multicast.Disillusionize
@RonMaupin on my Xiaomi Redmi 6A in Portable Hotspot mode universal 255.255.255.255 does not work but specialized 192.168.43.255 - does. So in general you are right, but it seems like Android has some filtering rules against 255.255.255.255 broadcasts, at least for some vendors and network configurations.Lowther
Why it failed with java.io.IOException: sendto failed: EPERM (Operation not permitted) . I have added <uses-permission android:name="android.permission.INTERNET"/>Sherrill
this answer is old and hasnt been updated, i suggest you try another way.Compartment
C
0

Here is my version :

I did a lot of benchmark described here

Note that the port must be the same

Sender :

fun sendBroadcast(context: Context, message: String) {
    val socket = DatagramSocket()
    socket.broadcast = true

    val address = getBroadcastAddress1(getLocalIP(context)!!)!!
    val buffer = message.toByteArray()
    val packet = DatagramPacket(buffer, buffer.size, address, 8888)

    socket.send(packet)
}

fun getLocalIP(context: Context): Inet4Address? {
    val manager =
        context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

    val props = manager.getLinkProperties(manager.activeNetwork)

    return props?.linkAddresses?.find {
    it.address is Inet4Address && it.flags == OsConstants.IFA_F_PERMANENT
    }?.address as Inet4Address?
}

fun getBroadcastAddress1(inet4Address: Inet4Address): InetAddress? {
    val temp: NetworkInterface
    var inetBroadcast: InetAddress? = null
    try {
        temp = NetworkInterface.getByInetAddress(inet4Address)
        val addresses = temp.interfaceAddresses
        for (inetAddress in addresses) inetBroadcast = inetAddress.broadcast
        return inetBroadcast
    } catch (e: SocketException) {
        e.printStackTrace()
    }
    return null
 }

Receiver :

fun receiveBroadcast() {
    val socket = DatagramSocket(8888, InetAddress.getByName("0.0.0.0"))

    while (true) {
        val buffer = ByteArray(1024)
        val packet = DatagramPacket(buffer, buffer.size)
        socket.receive(packet)

        val message = String(packet.data, 0, packet.length)
        Log.d("debug", "Broadcast received: $message")
    }
}
Christiachristian answered 23/6 at 17:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.