package it.uhopper.mqtt.service; import android.app.Service; import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.IBinder; import android.os.SystemClock; import android.util.Log; import org.eclipse.paho.client.mqttv3.MqttException; import java.util.Timer; public class MqttService extends Service { public final static String TAG = MqttService.class.getSimpleName(); MqttTask task; PingTimerTask timerTask; Timer timer; @Override public void onCreate() { super.onCreate(); //To change body of overridden methods use File | Settings | File Templates. } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (intent == null || intent.getAction() == null) { Log.e(TAG, "Null INTENT ACTION"); return START_REDELIVER_INTENT; } String s = intent.getAction(); //Is service ready ? if (!s.equals(MqttConstants.START) && serviceNotReady(intent)) { Log.e(TAG, "Starting the service before doing other things"); return START_STICKY; } if (s.equals(MqttConstants.NETUPDATE)) { Log.i(TAG, "NetUpdate"); return connectionUpdate(intent); } else if (s.equals(MqttConstants.START)) { Log.i(TAG, "START"); return _startService(intent); } else if (s.equals(MqttConstants.PUBLISH)) { Log.i(TAG, "publish"); return publish(intent); } else if (s.equals(MqttConstants.STOP)) { Log.i(TAG, "STOP"); //TODO stop pingtimer } else if (s.equals(MqttConstants.SUBSCRIBE)) { Log.i(TAG, "SUBSCRIBE"); return subscribeToTopic(intent); } else if (s.equals(MqttConstants.UNSUBSCRIBE)) { Log.i(TAG, "UNSUSCRIBE"); return unsubscribeToTopic(intent); } else if (s.equals(MqttConstants.PING)) { Log.i(TAG, "PING"); return handlePing(intent); } Log.e(TAG, "Wrong intent action!"); return START_REDELIVER_INTENT; } private int _startService(Intent intent) { Log.i(TAG, "++++++++++++++++++++++Starting service+++++++++++++++++++++"); String[] topics = intent.getStringArrayExtra("TOPICS"); if (topics == null) { topics = new String[0]; } int[] qos = intent.getIntArrayExtra("QOS"); if (qos == null) { qos = new int[0]; } MqttCallbackImplementation callback = new MqttCallbackImplementation(this); task = new MqttTask(this, topics, qos, callback); Thread t = new Thread(task); t.start(); //Start pingtimer Log.i(TAG, "Starting timer"); timer = new Timer(); timerTask = new PingTimerTask(this); timer.schedule(timerTask, MqttConstants.PING_PERIOD, MqttConstants.PING_PERIOD); return START_REDELIVER_INTENT; } private int publish(Intent intent) { String topic = intent.getStringExtra("TOPIC"); String payload = intent.getStringExtra("PAYLOAD"); int qos = intent.getIntExtra("QOS", 0); boolean retain = intent.getBooleanExtra("RETAIN", false); if (topic == null) { Log.e(TAG, "Missing Topic!"); return START_REDELIVER_INTENT; } if (payload == null) { payload = ""; } boolean succeded = task.publish(topic, payload, qos, retain); Log.d(TAG, "service publish data: " + succeded); if (!succeded) { //TODO maybe reinitialize the task and try again } return START_REDELIVER_INTENT; } private int connectionUpdate(Intent intent) { if (task == null || !intent.getBooleanExtra("connected", false)) { if (task == null) Log.e(TAG, "Received net update, but service is not initialized yet"); else Log.i(TAG, "Received net down update"); } else { Log.i(TAG, "Received a net up update"); Log.i(TAG, "Getting server location"); try { String host = MqttConstants.HOST; task.host = host; } catch (Exception e) { } Log.i(TAG, "Reinitializing mqttTask"); Thread t = new Thread(task); t.start(); Log.i(TAG, "End of connectionUpdate"); } return START_REDELIVER_INTENT; } private int subscribeToTopic(Intent intent) { String topic = intent.getStringExtra("TOPIC"); int qos = intent.getIntExtra("QOS", 0); if (topic == null) { Log.e(TAG, "Missing Topic!"); return START_STICKY; } try { task.addSubscription(topic, qos); } catch (MqttException e) { e.printStackTrace(); } return START_STICKY; } private int unsubscribeToTopic(Intent intent) { String topic = intent.getStringExtra("TOPIC"); if (topic == null) { Log.e(TAG, "Missing Topic!"); return START_STICKY; } try { task.removeSubscription(topic); } catch (MqttException e) { e.printStackTrace(); } return START_STICKY; } private int handlePing(Intent intent) { Log.i(TAG, "Topics: " + task.subscriptions()); if (task.isAlreadyConnected()) { Log.i(TAG, "Still Connected!"); } else { Log.e(TAG, "Not connected!!"); ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE); NetworkInfo info = cm.getActiveNetworkInfo(); boolean connected = info != null && info.isConnected(); if (connected) { Log.e(TAG, "but net is still ok"); Log.i(TAG, "try to reconnect"); Intent i = new Intent(this, MqttService.class); i.setAction(MqttConstants.NETUPDATE); i.putExtra("connected", true); Log.i("TAG", "Notify the service"); startService(i); } else { Log.e(TAG, "and no net :("); } } return START_STICKY; } private boolean serviceNotReady(final Intent intent) { try { task.isAlreadyConnected(); if (task.isInitialized() || intent.getAction().equals(MqttConstants.PING)) // TODO check return false; else { // If task not initialized still new Thread(new Runnable() { @Override public void run() { SystemClock.sleep(10000); startService(intent); //redeliver intent } }).start(); return true; } } catch (NullPointerException e) { Intent i = new Intent(this, MqttService.class); i.setAction(MqttConstants.START); startService(i); startService(intent);// redeliver old intent return true; } } public IBinder onBind(Intent intent) { return null; } }