package st.alr.mqttitude.services; import java.io.IOException; import java.util.Date; import java.util.EnumSet; import java.util.List; import java.util.Locale; import java.util.Set; import de.greenrobot.event.EventBus; import st.alr.mqttitude.App; import st.alr.mqttitude.R; import st.alr.mqttitude.support.Defaults; import st.alr.mqttitude.support.Events; import st.alr.mqttitude.support.GeocodableLocation; import st.alr.mqttitude.support.MqttPublish; import st.alr.mqttitude.support.Defaults.State; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.location.Address; import android.location.Geocoder; import android.os.IBinder; import android.preference.PreferenceManager; import android.util.Log; public abstract class ServiceLocator extends ServiceBindable implements MqttPublish { protected SharedPreferences sharedPreferences; private OnSharedPreferenceChangeListener preferencesChangedListener; protected Date lastPublish; private static Set<Defaults.State> state; private final String TAG = "ServiceLocator"; protected ServiceMqtt serviceMqtt; private ServiceConnection mqttConnection; private static ServiceLocator instance; @Override public void onCreate() { super.onCreate(); Log.v(this.TAG, "onCreate"); instance = this; this.started = false; this.sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); state = EnumSet.of(Defaults.State.Idle); preferencesChangedListener = new SharedPreferences.OnSharedPreferenceChangeListener() { @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreference, String key) { if(key.equals(Defaults.SETTINGS_KEY_BACKGROUND_UPDATES) || key.equals(Defaults.SETTINGS_KEY_BACKGROUND_UPDATES_INTERVAL)) handlePreferences(); } }; sharedPreferences.registerOnSharedPreferenceChangeListener(preferencesChangedListener); mqttConnection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { serviceMqtt = null; } @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.v(this.toString(), "bound"); serviceMqtt = (ServiceMqtt) ((ServiceBindable.ServiceBinder)service).getService(); } }; bindService(new Intent(this, ServiceMqtt.class), mqttConnection, Context.BIND_AUTO_CREATE); } abstract public GeocodableLocation getLastKnownLocation(); abstract protected void handlePreferences(); abstract public void enableForegroundMode(); abstract public void enableBackgroundMode(); public void publishLastKnownLocation() { Log.v(TAG, "publishLastKnownLocation"); lastPublish = new Date(); StringBuilder payload = new StringBuilder(); Date d = new Date(); GeocodableLocation l = getLastKnownLocation(); String topic = sharedPreferences.getString(Defaults.SETTINGS_KEY_TOPIC, Defaults.VALUE_TOPIC); //added unique ID for this app //String uid = sharedPreferences.getString(Defaults.SETTINGS_KEY_BROKER_USERNAME, "unknown"); Geocoder geo = new Geocoder(this.getApplicationContext(), Locale.getDefault()); String geoAddress = "Uknown"; List<Address> addresses; try { addresses = geo.getFromLocation(l.getLatitude(), l.getLongitude(), 1); if (addresses.isEmpty()) { //addres.setText("Waiting for Location"); } else { if (addresses.size() > 0) { geoAddress = addresses.get(0).getAddressLine(0) +", " + addresses.get(0).getLocality(); //Toast.makeText(getApplicationContext(), "Address:- " + addresses.get(0).getFeatureName() + addresses.get(0).getAdminArea() + addresses.get(0).getLocality(), Toast.LENGH_LONG).show(); geoAddress = geoAddress.trim(); } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (topic == null) { addState(State.NOTOPIC); return; } if (l == null) { this.addState(State.LocatingFail); return; } payload.append("{"); payload.append("\"_type\": ").append("\"").append("location").append("\""); payload.append(", \"lat\": ").append("\"").append(l.getLatitude()).append("\""); payload.append(", \"lon\": ").append("\"").append(l.getLongitude()).append("\""); payload.append(", \"tst\": ").append("\"").append((int)(d.getTime()/1000)).append("\""); payload.append(", \"acc\": ").append("\"").append(Math.round(l.getLocation().getAccuracy() * 100) / 100.0d).append("m").append("\""); payload.append(", \"alt\": ").append("\"").append(l.getLocation().getAltitude()).append("\""); payload.append(", \"gca\": ").append("\"").append(geoAddress).append("\""); payload.append("}"); ServiceMqtt.getInstance().publish( topic, payload.toString(), sharedPreferences.getBoolean(Defaults.SETTINGS_KEY_RETAIN, Defaults.VALUE_RETAIN), Integer.parseInt(sharedPreferences.getString(Defaults.SETTINGS_KEY_QOS, Defaults.VALUE_QOS)) , 20, this, l); } @Override public void publishSuccessfull(Object extra) { Log.v(TAG, "publishSuccessfull"); this.resetState(); EventBus.getDefault().post(new Events.PublishSuccessfull(extra)); } public static Set<State> getState() { return state; } public static String getStateAsText() { int id = R.string.stateIdle; if(state != null) { if (state.contains(State.Publishing)) id = R.string.statePublishing; else if (state.contains(State.PublishConnectionWaiting)) id = R.string.stateWaiting; else if (state.contains(State.PublishConnectionTimeout)) id = R.string.statePublishTimeout; else if (state.contains(State.LocatingFail)) id = R.string.stateLocatingFail; else if (state.contains(State.NOTOPIC)) id = R.string.stateNotopic; } return App.getInstance().getString(id); } @Override public void publishFailed(Object extra) { Log.e(TAG, "publishTimeout"); this.addState(State.PublishConnectionTimeout); } @Override public void publishing(Object extra) { Log.v(TAG, "publishing"); this.addState(State.Publishing); } @Override public void publishWaiting(Object extra) { Log.v(TAG, "waiting for broker connection"); this.addState(State.PublishConnectionWaiting); } protected void setStateTo(State s) { state.clear(); state.add(s); } protected void addState(State s) { state.add(s); if (isTickerState(s)) { App.getInstance().updateTicker(getStateAsText()); } App.getInstance().updateNotification(); EventBus.getDefault().post(new Events.StateChanged()); } private boolean isTickerState(State s) { return s == Defaults.State.LocatingFail || s == Defaults.State.NOTOPIC || s == Defaults.State.PublishConnectionTimeout || s == Defaults.State.PublishConnectionWaiting || (s == Defaults.State.PublishConnectionWaiting && sharedPreferences.getBoolean(Defaults.SETTINGS_KEY_TICKER_ON_PUBLISH, Defaults.VALUE_TICKER_ON_PUBLISH)); } protected void removeState(State s) { state.remove(s); EventBus.getDefault().post(new Events.StateChanged()); } public void resetState() { this.setStateTo(State.Idle); EventBus.getDefault().post(new Events.StateChanged()); App.getInstance().updateNotification(); } public Date getLastPublishDate() { return lastPublish; } public boolean areBackgroundUpdatesEnabled() { return sharedPreferences.getBoolean(Defaults.SETTINGS_KEY_BACKGROUND_UPDATES, Defaults.VALUE_BACKGROUND_UPDATES); } public int getUpdateIntervall() { return Integer.parseInt(sharedPreferences.getString(Defaults.SETTINGS_KEY_BACKGROUND_UPDATES_INTERVAL, Defaults.VALUE_BACKGROUND_UPDATES_INTERVAL)); } public int getUpdateIntervallInMiliseconds() { return getUpdateIntervall() * 60 * 1000; } }