package com.door43.translationstudio.service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import com.door43.tools.reporting.Logger;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Timer;
import java.util.TimerTask;
/**
* Broadcasts services provided by this device on the network
*/
public class BroadcastService extends NetworkService {
public static final String PARAM_BROADCAST_PORT = "param_broadcast_udp_port";
public static final String PARAM_SERVICE_PORT = "param_service_tcp_port";
public static final String PARAM_FREQUENCY = "param_broadcast_frequency";
public static final int TS_PROTOCAL_VERSION = 2;
private final IBinder mBinder = new LocalBinder();
private DatagramSocket mSocket;
private Timer mTimer;
private static Boolean mIsRunning = false;
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/**
* Sets whether or not the service is running
* @param running
*/
protected void setRunning(Boolean running) {
mIsRunning = running;
}
/**
* Checks if the service is currently running
* @return
*/
public static boolean isRunning() {
return mIsRunning;
}
@Override
public void onCreate() {
Logger.i(this.getClass().getName(), "Starting broadcaster");
mTimer = new Timer();
try {
mSocket = new DatagramSocket();
mSocket.setBroadcast(true);
} catch (SocketException e) {
// TODO: notify app
Logger.e(this.getClass().getName(), "Failed to start the broadcaster", e);
stopService();
return;
}
}
public int onStartCommand(Intent intent, int flags, int startid) {
if(intent != null) {
Bundle args = intent.getExtras();
if (args != null) {
setRunning(true);
final int udpPort = args.getInt(PARAM_BROADCAST_PORT);
final int serviceTCPPort = args.getInt(PARAM_SERVICE_PORT);
final int broadcastFrequency = args.getInt(PARAM_FREQUENCY, 2000);
JSONObject json = new JSONObject();
try {
json.put("version", TS_PROTOCAL_VERSION);
json.put("port", serviceTCPPort);
} catch (JSONException e) {
// TODO: 11/24/2015 notify app
Logger.e(this.getClass().getName(), "Failed to prepare the broadcast payload", e);
stopService();
return START_NOT_STICKY;
}
String data = json.toString();
// prepare packet
if (data.length() > 1024) {
// TODO: notify app
Logger.w(this.getClass().getName(), "The broadcast data cannot be longer than 1024 bytes");
stopService();
return START_NOT_STICKY;
}
InetAddress ipAddress;
try {
ipAddress = getBroadcastAddress();
} catch (UnknownHostException e) {
// TODO: notify app
Logger.e(this.getClass().getName(), "Failed to get the broadcast ip address", e);
stopService();
return START_NOT_STICKY;
}
final DatagramPacket packet = new DatagramPacket(data.getBytes(), data.length(), ipAddress, udpPort);
// schedule broadcast
mTimer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
try {
mSocket.send(packet);
} catch (IOException e) {
Logger.e(this.getClass().getName(), "Failed to send the broadcast packet", e);
}
}
}, 0, broadcastFrequency);
return START_STICKY;
}
}
Logger.w(this.getClass().getName(), "The broadcaster requires arguments to operate correctly");
stopService();
return START_NOT_STICKY;
}
@Override
public void onDestroy() {
stopService();
}
/**
* Stops the service
*/
private void stopService() {
if(mTimer != null) {
mTimer.cancel();
}
if(mSocket != null) {
// TODO: 11/20/2015 notify network that we are shutting down
// close
mSocket.close();
}
setRunning(false);
Logger.i(this.getClass().getName(), "Stopping broadcaster");
}
/**
* Class to retrieve instance of service
*/
public class LocalBinder extends Binder {
public BroadcastService getServiceInstance() {
return BroadcastService.this;
}
}
}