Sending Wake on LAN packet from Android to PC

Squonk picture Squonk · Apr 15, 2011 · Viewed 17.3k times · Source

My Android app sends/retrieves data to/from the user's own PC using HTTP and it's working fine with a handful of beta testers. I now need to consider a situation where the PC is hibernating.

I've never done this before but I've googled to find info about the WOL 'magic packet' and some simple source written in C (using CAsyncSocket at the client end). Doing this over a wi-fi connection on the user's home network is likely to be relatively straight-forward but ideally I want this to work over mobile internet (assuming the user can configure their home router to accept / forward the packet).

I'm guessing I need to use some generic Java network code and I've been looking at java.net.

At this point I can't decide whether I should be using java.net.Socket or java.net.DatagramSocket. So the question is, am I approaching this the right way and which of the two socket types should I be using (or would both suffice)? Many thanks.

Answer

Chris.Jenkins picture Chris.Jenkins · Dec 1, 2012

I can't take too much credit for it as its from this site

But this is a java version of wake on lan class:

public static final int PORT = 9;    

public static void main(String[] args) {

    if (args.length != 2) {
        System.out.println("Usage: java WakeOnLan <broadcast-ip> <mac-address>");
        System.out.println("Example: java WakeOnLan 192.168.0.255 00:0D:61:08:22:4A");
        System.out.println("Example: java WakeOnLan 192.168.0.255 00-0D-61-08-22-4A");
        System.exit(1);
    }

    String ipStr = args[0];
    String macStr = args[1];

    try {
        byte[] macBytes = getMacBytes(macStr);
        byte[] bytes = new byte[6 + 16 * macBytes.length];
        for (int i = 0; i < 6; i++) {
            bytes[i] = (byte) 0xff;
        }
        for (int i = 6; i < bytes.length; i += macBytes.length) {
            System.arraycopy(macBytes, 0, bytes, i, macBytes.length);
        }

        InetAddress address = InetAddress.getByName(ipStr);
        DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, PORT);
        DatagramSocket socket = new DatagramSocket();
        socket.send(packet);
        socket.close();

        System.out.println("Wake-on-LAN packet sent.");
    }
    catch (Exception e) {
        System.out.println("Failed to send Wake-on-LAN packet: + e");
        System.exit(1);
    }

}

private static byte[] getMacBytes(String macStr) throws IllegalArgumentException {
    byte[] bytes = new byte[6];
    String[] hex = macStr.split("(\\:|\\-)");
    if (hex.length != 6) {
        throw new IllegalArgumentException("Invalid MAC address.");
    }
    try {
        for (int i = 0; i < 6; i++) {
            bytes[i] = (byte) Integer.parseInt(hex[i], 16);
        }
    }
    catch (NumberFormatException e) {
        throw new IllegalArgumentException("Invalid hex digit in MAC address.");
    }
    return bytes;
}

Of course you will need to modify this to work with android (very little work needed) but I found it works better than @Bear's answer.