2

I am trying to make an app that will notify the user when data the app receives is not what it should be (think steam being below 212 degrees Fahrenheit). The app also shows the information if the user is in the app. I was able to get the notification to send whenever this was the case. The only problem is that the information needs to be really up-to-date, so it is updated every 10 seconds. This makes the app send a notification every 10 seconds if the data is continuously incorrect. Is there a way to prevent recurring notifications for a specified time? (Around 10 - 15 minutes)

I have tried using thread.sleep(1000) inside a for loop to make it wait the 10 minutes, but that pauses the entire updating system for 10 minutes, so no information is going to the app. I am new to android studio and couldn't find anything online to help me with this.

This is just the way the app knows to send a notification. If I could continue using this, that would be ideal, but if there is a better way, I am open to changing it.

 //ERROR Notification
    if (map.get("steamTemp") < 212 || map.get("steamTemp") > 500 || 
        map.get("waterTemp") < 40 || map.get("waterTemp") > 150|| 
        map.get("dieselFlow") < 50 || map.get("dieselFlow") > 100 || 
        map.get("waterFlow") < 50 || map.get("waterFlow") > 100|| 
        map.get("waterFeederLevel") < 10 || map.get("waterFeederLevel") > 150) {
        NotificationManager notif = (NotificationManager) 
            getSystemService(Context.NOTIFICATION_SERVICE);
        Notification notify = new Notification.Builder

            (getApplicationContext())                                                        
                .setContentTitle("ERROR: Device Error")
                .setContentText("Please see app for more information.")
                .setSmallIcon(R.drawable.error_notif)
                .setSound(soundUri)
                .build();

notify.flags |= Notification.FLAG_AUTO_CANCEL;
notif.notify(0, notify);

}

I would like a notification to be sent the moment something is wrong, but after that to wait 10 minutes before sending another one. The problem with the thread.sleep(1000) example I explained above is that it paused the entire app, not just the notification. This is not okay as the app needs to show updated information if the user looks at it.

Jackson148
  • 115
  • 1
  • 2
  • 9
  • 1
    One idea, can be save the time of the notification in the preferences and later when another notification arrived you get the time for the preferences and verify is they passed 10 minutes or the time you want :D – Carlosgub Sep 06 '19 at 20:34

1 Answers1

1

As carlosgub mentioned, you can use preferences hard-coded by yourself or entered by the user to determine when to send them. Here is some sample code:

import android.content.Context;
import android.content.SharedPreferences;

import java.util.Date;

public class YourClass {

    //Key in Shared Preferences to use
    private static final String LAST_UPDATE = "lastUpdate";
    //10 minutes, adjust to your preferences
    private static final long NUMBER_MILLISECONDS_BETWEEN_UPDATES = (1000L * 60L * 10L);
    //Your Shared Preferences name
    private static final String SP_NAME = "yourSPName";

    private static void saveLastUpdateTime(Context context) {
        SharedPreferences sharedPref = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPref.edit();
        long x = new Date().getTime();
        editor.putLong(LAST_UPDATE, x);
        editor.commit();
    }

    private static long getLastUpdateTime(Context context) {
        SharedPreferences sharedPref = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
        return sharedPref.getLong(LAST_UPDATE, -1);
    }

    public static boolean shouldSendNotification(Context context) {
        long lastUpdate = getLastUpdateTime(context);
        if (lastUpdate == -1) {
            saveLastUpdateTime(context);
            //This means it has yet to run
            return true;
        }
        long now = new Date().getTime();
        if ((now - lastUpdate) > NUMBER_MILLISECONDS_BETWEEN_UPDATES) {
            saveLastUpdateTime(context);
            return true;
        } else {
            return false;
        }
    }
}

In the code here, you call shouldSendNotification() and if it returns false, it has yet to be 10 minutes since the last time it ran, if it returns true, it has been over 10 minutes since the last time it ran (or has never run at all).

To use this with your code, at the top of the method that is building the notify object, just call it and if it returns false, return out:

if(!YourClass.shouldSendNotification(context)){
    return;
}

Just make sure to adjust the values up top to your preferences (Pun intended).

PGMacDesign
  • 6,092
  • 8
  • 41
  • 78
  • Thanks for the help! I think this is going to work. I am unfamiliar with android app development in general and especially with this way of coding, hence why I asked the question in the first place. Because of this, I need some help troubleshooting. When I run the program, I get this error: "Attempt to invoke virtual method 'android.content.SharedPreferences android.content.Context.getSharedPreferences(java.lang.String, int)' on a null object reference"Do I have it in the wrong location? Or is there something else I need to do? Thanks again for all the help! – Jackson148 Sep 09 '19 at 19:42
  • 1
    That error appears whenever you are trying to take an action (getSharedPreferences()) using a null object (context). In this case, the variable you are passing, the context, is null, which is causing the issue. If you want to message me and show the code you are using or just want to create a link to a [Gist](https://gist.github.com/) with your code and post it, I will be happy to take a look at it. – PGMacDesign Sep 09 '19 at 20:12
  • I think this is what you are looking for. I am also fairly new to GitHub, so if there is something else you need me to do, let me know. [MyGist](https://gist.github.com/Jackosn6513/9c638ab400baf3e81bffe08411b01286) The app receives the information from Amazon's AWS cognito, so that is why it might look a little weird. – Jackson148 Sep 10 '19 at 18:58
  • 1
    No worries, all you need to do is on line 190, right below `setContentView(R.layout.activity_main);` add this line of code: `this.context = this.getApplicationContext();` and it should resolve your issue. Normally we would use the Activity context, but this is for something that will trigger if the activity could be closed, in which case you would want it to still fire off. – PGMacDesign Sep 10 '19 at 19:57
  • Okay, it's no longer throwing an error and crashing the program, so thanks for the help with that. Now that I am able to run the program, it is still sending the notifications every time. I printed the ```LAST_UPDATE``` variable before and after this line in the getLastUpdateTime method: ```SharedPreferences sharedPref = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);``` It prints out that the variable is not changing. I believe the line ```return sharedPref.getLong(LAST_UPDATE, -1);``` is supposed to change this, correct? If not, where should I look to troubleshoot this? – Jackson148 Sep 10 '19 at 20:13
  • 1
    @Jackson148 Good catch! I had a logic error in the code above; it has since been fixed. Give that a try to see if it is working properly. – PGMacDesign Sep 12 '19 at 15:29