I'm making an app that does stuff in time intervals. The absolute longest i can wait between the updates is 30 seconds, anything between that and 0 is acceptable but i prefer 15 seconds for good measure. However, its not as easy as it sounds. I tried 4 methods, all of which are unacceptable for various reasons.
Keep in mind these problems occur in a Service
, when this code is run in an Activity
it runs fine. I also noticed that when the phone is plugged into my computer for debugging purposes, solution 3 run perfectly fine until i plug it out. I checked my battery settings, and there are no battery saving modes or other stuff like that, that could be the reason for this.
1.IntentService
that does stuff and then reschedules itself in 15 seconds. Unfortunately AlarmManager.setExact() is completely unreliable when it comes to the alarms being exact, as i described in this tumbleweed: Android Alarm not triggering at exact time
2.Foreground service that has a Thread
. In that thread i do my stuff and then sleep()
for 15 seconds. This method turned out to be even worse than previous, the thread was being woken up to 5 minutes past the proper time.
3.Then i tried using Timer
(as geokavel suggested) and scheduling work using scheduleAtFixedRate
and schedule
but the work was being done about 15-45 seconds too late, making the intervals to about 1 minute instead of 15 seconds.
4.The last way i thought of to achieve this is to not sleep in the Thread
in the foreground service from above. Instead, i compare the time:
public void run(){
nextTime = System.currentTimeMillis() + sleep;
while (true){
if (System.currentTimeMillis() >= nextTime) {
nextTime = System.currentTimeMillis() + sleep;
//do stuff
}
}
}
This method works like a charm except for one major downside- it uses 20-25% of the CPU all the time.
So my question is, is there maybe a way to make one the above solutions work properly(without their unacceptable downsides)? If not, is there a better way that i missed? Feel free to ask for more detail if needed.
EDIT: Requested code of run():
public void run(){
try {
if (Thread.currentThread().isInterrupted()){
throw new InterruptedException();
}
NetworkInfo info = cm.getActiveNetworkInfo();
if (info == null) {
throw new UnknownHostException();
}
if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
Log.i(TAG, "Won't use mobile connection");
throw new UnknownHostException();
} else {
internetRestored();
st.updateData();
}
} catch (MalformedURLException | UnknownHostException e) {
internetFailed();
Log.e(TAG, "No internet connection, cant log");
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
Log.i(TAG, "Thread iterrupted");
}
}