package com.notificationFramework.stimulus; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import com.notificationFramework.sedentary.frontEnd.R; import com.notificationFramework.sedentary.frontEnd.SaveFile; import com.notificationFramework.stimulusStrategy.StimulusStrategy; import java.util.Calendar; /** * Created by Peter De Jonckheere on 09/01/2018. * <p> * The main implementation of the Stimulus interface which handles strategies and requests * surrounding sedentary behaviour and its related notifications. * * @see android.content.BroadcastReceiver */ public class SedentaryStimulus extends BroadcastReceiver implements Stimulus { /** * The strategy which is used for a given run of the application. Saved statically to be * accessed from within the broadcast receiver's onReceive() method whihc is not in the same * instance of SedentaryStimulus. */ private static StimulusStrategy strategy; private final int threshold = 10; /** * Empty constructor required by the manifest to define this class as a broadcast receiver */ public SedentaryStimulus() { } /** * Available in case a default strategy is required to be used as one has not been chosen. * Currently unused. * * @param context the application context used to instantiate this object */ public SedentaryStimulus(Context context) { chooseStrategy(null, context); } /** * The main constrcutor used to define a specific strategy. * * @param context the application context used to instantiate this object * @param s the StimulusStrategy to be used as a strategy * @see com.notificationFramework.stimulusStrategy.StimulusStrategy */ public SedentaryStimulus(Context context, StimulusStrategy s) { chooseStrategy(s, context); } /** * Starts the service of the strategy passed to the constructor. * * @param s the chosen StimulusStrategy * @param context the application context within which this method was called */ private void chooseStrategy(StimulusStrategy s, Context context) { if (s != null) { strategy = s; } else { strategy = defaultStrategy; } Intent intent = new Intent(context, strategy.getClass()); context.startService(intent); } /** * The method called when a broadcast is received from a strategy class. After checking the time * and if notifications are set to be on, the notification implementation related to this * stimulus is started. * * @param context the context from which the broadcast was sent * @param intent the intent with which the broadcast was sent */ @Override public void onReceive(Context context, Intent intent) { SharedPreferences shared = context.getSharedPreferences(context.getString(R.string.preference_file_key), Context.MODE_PRIVATE); if ((checkTime(shared, context)) && (shared.getBoolean(context.getString(R.string.notf_switch), true)) && checkAcknowledged(shared, context) && checkContext(shared, context)) { Log.d("SEDSTIM", "SENDING NOTIFICATION"); Intent i = new Intent(context.getApplicationContext(), com.notificationFramework.notification.SedentaryNotification.class); context.getApplicationContext().startService(i); } else{ Log.d("SEDSTIM", "SENDING NOTIFICATION FAILED"); } if (strategy == null) { strategy = defaultStrategy; } Intent intent1 = new Intent(context, strategy.getClass()); context.stopService(intent1); chooseStrategy(strategy, context.getApplicationContext()); } /** * Checks the current time against the do not disturb time by first checking if the time spans 2 * days, then checking between the first time and midnight, then midnight and the second time, * followed finally by the simple check between the two times if the time does not span 2 days. * It is done in this way to avoid compications with date changes as each time is obtained using * the current calendar as a template so if done correctly dates should not need to be changed. * * @param shared the SharedPreferences instance set up in the onReceive() method * @param context the application context which this method has been called from * @return false if the time is within the do not disturb period and so a notification should * not be sent, true if a notification should be sent */ private boolean checkTime(SharedPreferences shared, Context context) { Calendar start = Calendar.getInstance(); start.set(Calendar.HOUR_OF_DAY, shared.getInt(context.getString(R.string.dnd_shour), 23)); start.set(Calendar.MINUTE, shared.getInt(context.getString(R.string.dnd_smin), 0)); Calendar midnightCal = Calendar.getInstance(); midnightCal.set(Calendar.HOUR_OF_DAY, 23); midnightCal.set(Calendar.MINUTE, 59); midnightCal.set(Calendar.SECOND, 59); Calendar end = Calendar.getInstance(); end.set(Calendar.HOUR_OF_DAY, shared.getInt(context.getString(R.string.dnd_ehour), 9)); end.set(Calendar.MINUTE, shared.getInt(context.getString(R.string.dnd_emin), 0)); Calendar curCal = Calendar.getInstance(); if (shared.getInt(context.getString(R.string.dnd_shour), 23) > shared.getInt(context.getString(R.string.dnd_ehour), 9)) { if (curCal.getTime().after(start.getTime()) && curCal.getTime().before(midnightCal.getTime())) { return false; } else { midnightCal.set(Calendar.HOUR_OF_DAY, 0); midnightCal.set(Calendar.MINUTE, 0); midnightCal.set(Calendar.SECOND, 1); if (curCal.getTime().after(midnightCal.getTime()) && curCal.getTime().before(end.getTime())) { return false; } else { return true; } } } else if (curCal.getTime().after(start.getTime()) && curCal.getTime().before(end.getTime())) { return false; } else { return true; } } //Returns true if notification is to be sent private boolean checkAcknowledged(SharedPreferences shared, Context context){ int period = shared.getInt(context.getString(R.string.daily_goal), context.getResources().getInteger(R.integer.daily_goal_minutes)); float ackThreshold = (24/period); ackThreshold = ackThreshold * threshold; Log.d("AVGTHRESH", String.valueOf(ackThreshold)); float avgAck = shared.getFloat(context.getString(R.string.avg_ack), 0); Log.d("AVGACK", String.valueOf(avgAck)); if(avgAck > ackThreshold){ Intent i = new Intent(context.getApplicationContext(), com.notificationFramework.stimulus.FeedbackStimulus.class); LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context.getApplicationContext()); lbm.sendBroadcast(i); SaveFile.recordNotification(0,0,0,1, context); return false; }else{ return true; } } private boolean checkContext(SharedPreferences shared, Context context){ int mostPop = shared.getInt(context.getString(R.string.store_mcp), -1); float temp = shared.getFloat(context.getString(R.string.store_temp), 18); int lastPlace = shared.getInt(context.getString(R.string.store_place), 0); int ackTotal = shared.getInt(context.getString(R.string.ack_total), 0); int placeAck = shared.getInt(context.getString(R.string.place_ack_total), 0); double comp = (double) placeAck / ackTotal; if(comp < 0.2){ return false; }else /*if (lastPlace >= 0 && lastPlace < 999) { //Assume work return false; } else if(temp > 18){ //Assume hot so outside??? return false; }else */{ return true; } } }