package st.alr.mqttitude;
import java.text.SimpleDateFormat;
import java.util.Date;
import st.alr.mqttitude.services.ServiceLocator;
import st.alr.mqttitude.services.ServiceLocatorFused;
import st.alr.mqttitude.services.ServiceMqtt;
import st.alr.mqttitude.support.Defaults;
import st.alr.mqttitude.support.Events;
import st.alr.mqttitude.support.GeocodableLocation;
import st.alr.mqttitude.support.ReverseGeocodingTask;
import android.app.Application;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.location.Location;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import de.greenrobot.event.EventBus;
//import com.bugsnag.android.Bugsnag;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
public class App extends Application {
private static App instance;
private static SharedPreferences sharedPreferences;
private SharedPreferences.OnSharedPreferenceChangeListener preferencesChangedListener;
private NotificationManager notificationManager;
private static NotificationCompat.Builder notificationBuilder;
private static Class<?> locatorClass;
private GeocodableLocation lastPublishedLocation;
private Date lastPublishedLocationTime;
private boolean even = false;
private SimpleDateFormat dateFormater;
private Handler handler;
@Override
public void onCreate() {
super.onCreate();
int resp = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
instance = this;
//Bugsnag.register(this, Defaults.BUGSNAG_API_KEY);
//Bugsnag.setNotifyReleaseStages("production", "testing");
handler = new Handler() {
public void handleMessage(Message msg) {
onHandlerMessage(msg);
}
};
EventBus.getDefault().register(this);
Intent serviceLocator = null;
if (resp == ConnectionResult.SUCCESS) {
Log.v(this.toString(), "Play services version: " + GooglePlayServicesUtil.GOOGLE_PLAY_SERVICES_VERSION_CODE);
locatorClass = ServiceLocatorFused.class;
} else {
// TODO: implement fallback locator
Log.e(this.toString(), "play services not available and no other locator implemented yet ");
locatorClass = ServiceLocatorFused.class;
}
serviceLocator = new Intent(this, getServiceLocatorClass());
this.dateFormater = new SimpleDateFormat("y/M/d H:m:s", getResources().getConfiguration().locale);
notificationManager = (NotificationManager) App.getInstance().getSystemService(
Context.NOTIFICATION_SERVICE);
notificationBuilder = new NotificationCompat.Builder(App.getInstance());
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
preferencesChangedListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreference, String key) {
if (key.equals(Defaults.SETTINGS_KEY_NOTIFICATION_ENABLED))
handleNotification();
}
};
sharedPreferences.registerOnSharedPreferenceChangeListener(preferencesChangedListener);
handleNotification();
Log.v(this.toString(), "Starting MQTT service ");
startService(new Intent(this, ServiceMqtt.class)); // Service remains running after binds by activity
Log.v(this.toString(), "Starting locator service " + getServiceLocatorClass().toString());
startService(serviceLocator); // Service remains running after binds by activity
}
public String formatDate(Date d) {
return dateFormater.format(d);
}
public static App getInstance() {
return instance;
}
/**
* @category NOTIFICATION HANDLING
*/
private void handleNotification() {
Log.v(this.toString(), "handleNotification()");
notificationManager.cancel(Defaults.NOTIFCATION_ID);
if (notificationEnabled())
createNotification();
}
private boolean notificationEnabled() {
return sharedPreferences.getBoolean(Defaults.SETTINGS_KEY_NOTIFICATION_ENABLED, Defaults.VALUE_NOTIFICATION_ENABLED);
}
private void createNotification() {
Intent resultIntent = new Intent(App.getInstance(), ActivityMain.class);
android.support.v4.app.TaskStackBuilder stackBuilder = android.support.v4.app.TaskStackBuilder
.create(this);
stackBuilder.addParentStack(ActivityMain.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT);
notificationBuilder.setContentIntent(resultPendingIntent);
updateNotification();
}
public void updateTicker(String text) {
notificationBuilder.setTicker(text + ((even = even ? false : true) ? " " : ""));
notificationBuilder.setSmallIcon(R.drawable.ic_notification);
notificationManager.notify(Defaults.NOTIFCATION_ID, notificationBuilder.build());
// if the notification is not enabled, the ticker will create an empty one that we get rid of
if(!notificationEnabled())
notificationManager.cancel(Defaults.NOTIFCATION_ID);
}
public void updateNotification() {
if(!notificationEnabled())
return;
String title = null;
String subtitle = null;
long time = 0;
if(lastPublishedLocation != null && sharedPreferences.getBoolean("notificationLocation", true)) {
time = lastPublishedLocation.getLocation().getTime();
if(lastPublishedLocation.getGeocoder() != null && sharedPreferences.getBoolean("notificationGeocoder", false)) {
title = lastPublishedLocation.getGeocoder();
} else {
title = lastPublishedLocation.getLatitude() + ":" + lastPublishedLocation.getLongitude();
}
} else {
title = getString(R.string.app_name);
}
subtitle = ServiceLocator.getStateAsText() + " | " + ServiceMqtt.getConnectivityText();
notificationBuilder.setContentTitle(title);
notificationBuilder
.setSmallIcon(R.drawable.ic_notification)
.setContentText(subtitle)
.setPriority(NotificationCompat.PRIORITY_MIN);
if(time != 0)
notificationBuilder.setWhen(lastPublishedLocationTime.getTime());
notificationManager.notify(Defaults.NOTIFCATION_ID, notificationBuilder.build());
}
// public void onEventMainThread(Events.StateChanged e) {
// updateNotification();
// }
public void onEventMainThread(Events.MqttConnectivityChanged e) {
updateNotification();
}
public void onEventMainThread(Events.StateChanged e) {
updateNotification();
}
private void onHandlerMessage(Message msg) {
switch (msg.what) {
case ReverseGeocodingTask.GEOCODER_RESULT:
geocoderAvailableForLocation(((GeocodableLocation) msg.obj));
break;
}
}
private void geocoderAvailableForLocation(GeocodableLocation l) {
if(l == lastPublishedLocation) {
Log.v(this.toString(), "geocoder now available for lastPublishedLocation");
updateNotification();
} else {
Log.v(this.toString(), "geocoder now available for an old location");
}
}
public void onEvent(Events.PublishSuccessfull e) {
Log.v(this.toString(), "Publish successful");
if(e.getExtra() != null && e.getExtra() instanceof GeocodableLocation) {
GeocodableLocation l = (GeocodableLocation) e.getExtra();
this.lastPublishedLocation = l;
this.lastPublishedLocationTime = e.getDate();
if(sharedPreferences.getBoolean("notificationGeocoder", false))
(new ReverseGeocodingTask(this, handler)).execute(new GeocodableLocation[] {l});
updateNotification();
// This is a bit hacked as we append an empty space on every second
// ticker update. Otherwise consecutive tickers with the same text would
// not be shown
if(sharedPreferences.getBoolean(Defaults.SETTINGS_KEY_TICKER_ON_PUBLISH,
Defaults.VALUE_TICKER_ON_PUBLISH))
updateTicker(getString(R.string.statePublished));
}
}
public void onEvent(Events.LocationUpdated e) {
if(e.getGeocodableLocation() == null)
return;
Log.v(this.toString(), "LocationUpdated: " + e.getGeocodableLocation().getLatitude() + ":"
+ e.getGeocodableLocation().getLongitude());
}
public boolean isDebugBuild(){
return 0 != ( getApplicationInfo().flags &= ApplicationInfo.FLAG_DEBUGGABLE );
}
public static Class<?> getServiceLocatorClass() {
return locatorClass;
}
}