package net.cmikavac.autowol.services;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Random;
import net.cmikavac.autowol.models.DeviceModel;
import net.cmikavac.autowol.R;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.os.AsyncTask;
import android.support.v4.app.NotificationCompat;
import android.widget.Toast;
public class WolService extends AsyncTask<DeviceModel, Void, String> {
private Context mContext = null;
private Boolean mNotify = false;
/**
* Constructor.
* @param context Context entity.
*/
public WolService(Context context, Boolean notify) {
mContext = context;
mNotify = notify;
}
/* (non-Javadoc)
* Wakes the device asynchronously.
* @see android.os.AsyncTask#doInBackground(Params[])
*/
@Override
protected String doInBackground(DeviceModel... devices) {
DeviceModel device = devices[0];
return Wake(device.getName(), device.getBroadcast(), device.getMac(), device.getPort());
}
/* (non-Javadoc)
* Creates a notification or toast message after device WOL attempt.
* @see android.os.AsyncTask#onPostExecute(java.lang.Object)
*/
@Override
protected void onPostExecute(String message) {
super.onPostExecute(message);
if (mNotify)
createNotification(message);
else
Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
}
/**
* Creates a WOL network packet and sends it to the network.
* @param name WOL device name.
* @param broadcast Access point broadcast IP/FQDN.
* @param mac MAC address of the device to wake.
* @param port WOL port to be used.
* @return Success/exception message.
*/
private String Wake(String name, String broadcast, String mac, int port) {
try {
byte[] macBytes = getMacBytes(mac);
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(broadcast);
DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, port);
DatagramSocket socket = new DatagramSocket();
socket.send(packet);
socket.close();
return "WOL packet sent to " + name + ".";
}
catch (Exception e) {
return "Failed to send WOL packet: " + e.getMessage();
}
}
/**
* Creates a byte array from MAC address.
* @param mac MAC address.
* @return Byte array representing MAC address.
* @throws IllegalArgumentException
*/
private static byte[] getMacBytes(String mac) throws IllegalArgumentException {
byte[] bytes = new byte[6];
String[] hex = mac.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;
}
/**
* Creates a new Android notification to let the user know Auto-WOL packet has been sent.
* @param message Message to display.
*/
private void createNotification(String message) {
Notification notification = new NotificationCompat.Builder(mContext)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Auto WOL")
.setContentText(message)
.build();
NotificationManager mNotificationManager = (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(new Random(System.currentTimeMillis()).nextInt() , notification);
}
}