From a1e3e432dedcff0f68b86797724792875de40c56 Mon Sep 17 00:00:00 2001 From: Peter De Jonckheere <peter.de-jonckheere.2014@uni.strath.ac.uk> Date: Mon, 25 Jun 2018 12:44:02 +0100 Subject: [PATCH] Added feedback notification --- src/main/AndroidManifest.xml | 4 + .../notification/FeedbackNotification.java | 60 ++++++++++++++ .../notification/GoalNotification.java | 2 + .../sedentary/frontEnd/DataAnalysis.java | 20 +++-- .../sedentary/frontEnd/SaveFile.java | 8 +- .../stimulus/FeedbackStimulus.java | 80 +++++++++++++++++++ .../stimulus/SedentaryStimulus.java | 9 ++- .../stimulusStrategy/Accelerometer.java | 1 - .../stimulusStrategy/SigMotionDetect.java | 1 - src/main/res/values/strings.xml | 1 + 10 files changed, 171 insertions(+), 15 deletions(-) create mode 100644 src/main/java/com/notificationFramework/notification/FeedbackNotification.java create mode 100644 src/main/java/com/notificationFramework/stimulus/FeedbackStimulus.java diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 282e65e..5933890 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -32,6 +32,8 @@ </service> <service android:name="com.notificationFramework.notification.GoalNotification"> </service> + <service android:name="com.notificationFramework.notification.FeedbackNotification"> + </service> <service android:name="com.notificationFramework.stimulusStrategy.Accelerometer"> </service> <service android:name="com.notificationFramework.stimulusStrategy.SigMotionDetect"> @@ -42,6 +44,8 @@ </receiver> <receiver android:name="com.notificationFramework.stimulus.GoalStimulus"> </receiver> + <receiver android:name="com.notificationFramework.stimulus.FeedbackStimulus"> + </receiver> <receiver android:name="com.notificationFramework.stimulus.BootLauncher"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"> diff --git a/src/main/java/com/notificationFramework/notification/FeedbackNotification.java b/src/main/java/com/notificationFramework/notification/FeedbackNotification.java new file mode 100644 index 0000000..f730a5c --- /dev/null +++ b/src/main/java/com/notificationFramework/notification/FeedbackNotification.java @@ -0,0 +1,60 @@ +package com.notificationFramework.notification; + +import android.annotation.TargetApi; +import android.app.NotificationChannel; +import android.content.Intent; +import android.support.v4.app.NotificationCompat; + +import com.notificationFramework.sedentary.frontEnd.R; + +/** + * Created by pharmacy on 25/06/2018. + */ + +public class FeedbackNotification extends SedentaryNotification { + + /** + * Called when the service is started. Uses the Notification implementation of this method. + * @param intent the intent used to start the service + * @param flags additional information about the start request + * @param startId the unique start id of this service + * @return the return value of the Notification implementation of this method + */ + @Override + public int onStartCommand(Intent intent, int flags, int startId){ + return super.onStartCommand(intent, flags, startId); + } + + /** + * Implementation of the abstract method specified in Notification which adds individual + * properties to the notification which is to be sent such as the content title and content + * text. + * + * @param builder the NotificationCompat.Builder provided to be altered with unique properties + * @return the altered version of 'builder' + */ + @Override + protected NotificationCompat.Builder setParameters(NotificationCompat.Builder builder) { + builder = super.setParameters(builder); + builder.setContentTitle(this.getClass().getSimpleName()); + builder.setContentText(this.getString(R.string.feedback)); + if (preferences.getBoolean(getString(R.string.vibration), false)) { + builder.setVibrate(new long[]{0, 500, 0, 500}); + } + return builder; + } + + /** + * Implementation of the abstract method specified in Notification which adds individual + * properties to the NotificationChannel used if the API level is above 26. + * + * @param nc the NotificationChannel to be altered with individual properties + * @return the altered version of NotificationChannel 'nc' + */ + @TargetApi(26) + protected NotificationChannel setChannelParameters(NotificationChannel nc) { + nc = super.setChannelParameters(nc); + nc.setDescription(this.getClass().getName()); + return nc; + } +} diff --git a/src/main/java/com/notificationFramework/notification/GoalNotification.java b/src/main/java/com/notificationFramework/notification/GoalNotification.java index 2f5575d..d111a5f 100644 --- a/src/main/java/com/notificationFramework/notification/GoalNotification.java +++ b/src/main/java/com/notificationFramework/notification/GoalNotification.java @@ -6,6 +6,7 @@ import android.content.Intent; import android.support.v4.app.NotificationCompat; import com.notificationFramework.sedentary.frontEnd.R; +import com.notificationFramework.sedentary.frontEnd.SaveFile; /** * Created by Peter De Jonckheere on 09/03/2018. @@ -43,6 +44,7 @@ public class GoalNotification extends SedentaryNotification { builder = super.setParameters(builder); builder.setContentTitle(this.getClass().getSimpleName()); builder.setContentText(preferences.getString(getString(R.string.goal_met), "Daily Goal Met")); + SaveFile.recordNotification(1, 1, 0, 0, this); if (preferences.getBoolean(getString(R.string.vibration), false)) { builder.setVibrate(new long[]{0, 500, 0, 500}); } diff --git a/src/main/java/com/notificationFramework/sedentary/frontEnd/DataAnalysis.java b/src/main/java/com/notificationFramework/sedentary/frontEnd/DataAnalysis.java index 05c2f44..58e7a74 100644 --- a/src/main/java/com/notificationFramework/sedentary/frontEnd/DataAnalysis.java +++ b/src/main/java/com/notificationFramework/sedentary/frontEnd/DataAnalysis.java @@ -2,7 +2,9 @@ package com.notificationFramework.sedentary.frontEnd; import android.app.NotificationManager; import android.content.Context; +import android.content.Intent; import android.content.SharedPreferences; +import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import java.text.ParseException; @@ -34,7 +36,11 @@ public class DataAnalysis { } catch(NullPointerException e){ Log.i("NOTIFICATION", "NOTIFICATION WAS CLICKED ON"); } - //Give new notification saying well done? + + Intent i = new Intent(context.getApplicationContext(), + com.notificationFramework.stimulus.FeedbackStimulus.class); + LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context.getApplicationContext()); + lbm.sendBroadcast(i); logAcknowledgement(context); return true; } else { @@ -47,18 +53,18 @@ public class DataAnalysis { SharedPreferences sharedPref = context.getSharedPreferences(context.getString(R.string.preference_file_key), Context.MODE_PRIVATE); int totalAck = sharedPref.getInt(context.getString(R.string.ack_total), 0); int ackDays = sharedPref.getInt(context.getString(R.string.ack_days), 1); - float avgAck; + float avgAck = 0; int currentDay = Calendar.getInstance().get(Calendar.DAY_OF_YEAR); + SharedPreferences.Editor editor = sharedPref.edit();; if (currentDay != sharedPref.getInt(context.getString(R.string.progress_day), 0)) { avgAck = totalAck / ackDays; ackDays++; - SharedPreferences.Editor editor = sharedPref.edit(); editor.putInt(context.getString(R.string.progress_day), currentDay); - editor.putInt(context.getString(R.string.ack_total), totalAck); - editor.putInt(context.getString(R.string.ack_days), ackDays); - editor.putFloat(context.getString(R.string.avg_ack), avgAck); - editor.commit(); } totalAck++; + editor.putInt(context.getString(R.string.ack_total), totalAck); + editor.putInt(context.getString(R.string.ack_days), ackDays); + editor.putFloat(context.getString(R.string.avg_ack), avgAck); + editor.commit(); } } \ No newline at end of file diff --git a/src/main/java/com/notificationFramework/sedentary/frontEnd/SaveFile.java b/src/main/java/com/notificationFramework/sedentary/frontEnd/SaveFile.java index 1592b78..4ea61b4 100644 --- a/src/main/java/com/notificationFramework/sedentary/frontEnd/SaveFile.java +++ b/src/main/java/com/notificationFramework/sedentary/frontEnd/SaveFile.java @@ -43,7 +43,7 @@ public class SaveFile { * @param context the application context which the method has been called from and which will * be used to access and write to the external storage of the device */ - private static void recordTimeStamp(int sent, int clicked, int acknowledged, Context context) { + private static void recordTimeStamp(int sent, int clicked, int movement, int acknowledged, Context context) { Calendar cal = Calendar.getInstance(); ArrayList<String> contents = new ArrayList<String>(); String line; @@ -71,8 +71,8 @@ public class SaveFile { } try { items = prevLine.split(" "); - if (items[6].equals("10")){ - if(DataAnalysis.analyse(prevLine, cal)){ + if (items[6].equals("10") && (movement == 1)){ + if(DataAnalysis.analyse(prevLine, cal, context)){ recordNotification(0,0,0,1, context); } } @@ -161,7 +161,7 @@ public class SaveFile { } } } - recordTimeStamp(sent, clicked, acknowledged, context); + recordTimeStamp(sent, clicked, movement, acknowledged, context); } /** diff --git a/src/main/java/com/notificationFramework/stimulus/FeedbackStimulus.java b/src/main/java/com/notificationFramework/stimulus/FeedbackStimulus.java new file mode 100644 index 0000000..fe93bba --- /dev/null +++ b/src/main/java/com/notificationFramework/stimulus/FeedbackStimulus.java @@ -0,0 +1,80 @@ +package com.notificationFramework.stimulus; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; + +import com.notificationFramework.sedentary.frontEnd.R; + +import java.util.Calendar; + +/** + * Created by pharmacy on 25/06/2018. + */ + +public class FeedbackStimulus extends BroadcastReceiver implements Stimulus { + + /** + * Upon receiving a broadcast from a strategy this method is triggered and starts the related + * service which sends the notification after checking relevant personalised settings. + * + * @param context the context of the broadcast + * @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))) { + Intent i = new Intent(context.getApplicationContext(), + com.notificationFramework.notification.FeedbackNotification.class); + context.getApplicationContext().startService(i); + } + + } + + /** + * 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; + } + } +} diff --git a/src/main/java/com/notificationFramework/stimulus/SedentaryStimulus.java b/src/main/java/com/notificationFramework/stimulus/SedentaryStimulus.java index 422bbe9..7eb7ff7 100644 --- a/src/main/java/com/notificationFramework/stimulus/SedentaryStimulus.java +++ b/src/main/java/com/notificationFramework/stimulus/SedentaryStimulus.java @@ -4,8 +4,10 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.support.v4.content.LocalBroadcastManager; import com.notificationFramework.sedentary.frontEnd.R; +import com.notificationFramework.sedentary.frontEnd.SaveFile; import com.notificationFramework.stimulusStrategy.StimulusStrategy; import java.util.Calendar; @@ -156,8 +158,11 @@ public class SedentaryStimulus extends BroadcastReceiver implements Stimulus { float ackThreshold = (24/period) * threshold; float avgAck = shared.getFloat(context.getString(R.string.avg_ack), 4); if(avgAck < ackThreshold){ - //Send well done notification - //Record unsent notification for fading and behavioural analysis purposes?? + 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; diff --git a/src/main/java/com/notificationFramework/stimulusStrategy/Accelerometer.java b/src/main/java/com/notificationFramework/stimulusStrategy/Accelerometer.java index dc66c73..a72ccc5 100644 --- a/src/main/java/com/notificationFramework/stimulusStrategy/Accelerometer.java +++ b/src/main/java/com/notificationFramework/stimulusStrategy/Accelerometer.java @@ -177,7 +177,6 @@ public class Accelerometer extends Service implements StimulusStrategy, SensorEv public void goalNotify() { Intent i = new Intent(getBaseContext(), com.notificationFramework.stimulus.GoalStimulus.class); - SaveFile.recordNotification(1, 1, 0, 0, this); LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this); lbm.sendBroadcast(i); } diff --git a/src/main/java/com/notificationFramework/stimulusStrategy/SigMotionDetect.java b/src/main/java/com/notificationFramework/stimulusStrategy/SigMotionDetect.java index 4587e84..95865b2 100644 --- a/src/main/java/com/notificationFramework/stimulusStrategy/SigMotionDetect.java +++ b/src/main/java/com/notificationFramework/stimulusStrategy/SigMotionDetect.java @@ -250,7 +250,6 @@ public class SigMotionDetect extends Service implements StimulusStrategy { public void goalNotify() { Intent i = new Intent(getBaseContext(), com.notificationFramework.stimulus.GoalStimulus.class); - SaveFile.recordNotification(1, 1, 0, 0, this); LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this); lbm.sendBroadcast(i); } diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index b615361..8fba562 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -47,4 +47,5 @@ <string name="ack_days">Acknowledgement Day Count</string> <string name="avg_ack">Acknowledgements per day</string> <string name="notf_id">Notification ID</string> + <string name="feedback">Well done!! Keep moving!</string> </resources> -- GitLab