I have this code called in a Service:
timer.scheduleAtFixedRate(new TimerTask(){
public void run() {
showNotification();
}
}, firstNotify, 86400000L);
It is my understanding that this should cause showNotification() to be called once per day at the same time each day, at the time specified in firstNotify (86400000 being the milliseconds in a day).
However, the notifies were happening approximately every 3 hours on my phone, and a little over 4 hours on my friend's phone. Is there any reason why these would be occurring faster than the specified 1-day period for repeating?
I know its not a direct answer to your question, but you should use AlarmManager in such cases as yours. See setRepeating function.
If your Service is not setup correctly and it is being shut down at some point, the Timer would be recreated and called again after a firstNotify delay. Does this sound possible? You might be better off using AlarmManager to create the timed event.
Related
The game I am working on is a missile-oriented GPS-based combat game on Android. The app checks every 15 minutes to see if the user is under attack by any other players, and if so, sends them a notification that they are under attack. Currently, because of the minimum 15 minute interval, the app sends these notifications either too late or not at all. What I need to do is alter this so that somehow, some way, the app checks the "under attack" status of the user more often than 15 minutes. Every minute or every 30 seconds would be ideal.
here is the doWork() method which starts the notification check:
{
if(!MainActivity.GetRunning())
{
Utilities.DebugLog(context, "AlertService", "Main activity not running. Firing notification service handler.");
NotificationServiceHandler handler = new NotificationServiceHandler(context);
handler.Start();
}
return Result.SUCCESS;
}
WorkManager is not a suitable tool for what you wish to do. You will need to use a foreground service and your own in-process timing engine (e.g., ScheduledExecutorService). That will not work for very long before Doze mode and other power-saving measures take effect, but hopefully your games are only an hour or so long.
Hej theBiscuit,
instead of using WorkManager, you could set up an AlarmManager to wake up the app and check for attacks.
If you want to do it while the app is running, a CountDownTimer could help for short periods of time.
I'm working on a CountDown app. I want to launch a 'end of countdown activity' when the countdown reaches 0. I have a variable keeping track of how much time is left (variable that I use to display the countdown).
The documentation gives me this (I have to use this method because it's part of the exercise):
public void setExact (int type,long triggerAtMillis,PendingIntent operation)
Knowing this I pass my countdown variable as the second argument thinking the activity would roughly be opened around the time I've given.
Let's say, I put a duration of 30s in the duration variable. I start the countdown by pushing a button and I use the 'setExact' method using the duration variable.
Even though, I pass 30s (obviously converted in millis), the 'end of countdown activity' launches only after 5s.
Feel free to download the project.
It sounds like you might be passing in 30000 for the trigger time, when it should probably be 30000 plus the current time in ms.
From the documentation:
triggerAtMillis long: time in milliseconds that the alarm should go off, using the appropriate clock (depending on the alarm type).
I'm building an Android organizer app.
I have an Event class that has a start time and I want to trigger some action when this time comes. So, how can I constantly compare this start time with current time, to know when it comes?
Thanks!
Instead of constantly checking for current time against scheduleStartTime, you can schedule task to trigger at scheduledStartTime.
You can use either JobScheduler or AlarmManager
https://developer.android.com/reference/android/app/job/JobInfo.Builder.html
https://code.tutsplus.com/tutorials/using-the-jobscheduler-api-on-android-lollipop--cms-23562
You can set when to trigger task by specifying time difference between start time and current time in millisecond.
builder.setPeriodic(5000);
Or you can also use Alarm manager
https://developer.android.com/training/scheduling/alarms.html
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, alarmIntent);
Hope this help
You could use one of the following solutions :
Have a time and on Timer tick, you could compare your start time against the current time and trigger you action if needed.
Or, you could use a ScheduledExecutorService to schedule the task you want to archive x seconds in the future base on the current time and the start time of your Event
As you are on Android, I would recommend to do this as part of a Service.
Hope this will help.
I'm trying to make a small application that shows a notification for each 10 minutes until reach 2 hours then the alarm should stop, when I used setRepeat() it works well but I couldn't stop it as I mentioned in my prevoise question HERE,,
I tried with many ways, but it still, there's a problem alarm didn't stop...
I have an idea to use mAlarmManager.set() inside loop, I wrote a code but the loop only start alarm for one time..
so, I'm here to ask how can I implement this idea and showing notification for each 10 minutes until 2 hours !!!
I'll be so appreciated if you help
thanks in advance ...
You don't want to put it in a loop. Rather, have the alarm's pending intent trigger code that checks how much time has gone by and cancels the alarm if appropriate. (This would go in the onReceive method of the class you created the PendingIntent with.)
Alternatively, you can set another alarm for two hours from the start time which will trigger the code to cancel the repeating alarm.
You can set alarm within a for loop too.
Example:
long next=0;
for (int i = 0; i < 12; i++) {
alarmManager.set(AlarmManager.RTC_WAKEUP, mCurrentTime + 10*60*1000 + next, pendingIntent);
next+=10*60*1000;
}
I'm developing a metronome application. The user can select at runtime the bpm, and my app will play the "tick" sound accordingly. The "tick" is a single metronome "shot" (mp3). I tried implementing it using Handler and MediaPlayer, but the metronome is not precise at all.
So I thought about changing the whole approach: when the user choose a new bpm value, I synthesize a new sound by repeating the tick sound X times every N milliseconds, then looping over this runtime created sound.
Is this a valid alternative? How can it be implemented in Android?
The alternative of looping through a synthesized sound seems to be the best choice for now. There was a great session about audio on Google I/O 2013 called High Performance Audio that I would certainly advice watching for having a deeper understanding on how the system works and what problems the developers will face when dealing with the audio latency. At about the 17:00 of the video, there is graph that shows jitter versus callbacks. In the perfect world that does not exist (oh really?), the jitter would be zero for all the scheduled audio callbacks made. But that is not the case, for there are jitters as high as 35 milliseconds or even greater, for the data in the graph was made using an unspecified ICS device and there are certainly worse scenarios than that.
So, as a metronome is a precision tool and these jitters are not good at all, the scheduled playback approach should be left aside. I even made an reasonably realiable metronome work with a synthesized sound using AudioTrack.
Hope it helps ^^
You could try to use a TimerTask scheduled for fixed-rate execution on a Timer.
Timer and TimerTask are both part of the Android SDK (and Java SE). The executions do not delay because of execution time of the previous event.
Timer timer = new Timer("MetronomeTimer", true);
TimerTask tone = new TimerTask(){
#Override
public void run(){
//Play sound
}
};
timer.scheduleAtFixedRate(tone, 500, 500); //120 BPM. Executes every 500 ms.
You can then cancel the TimerTask when you need to change the BPM.
tone.cancel();
tone = new TimerTask(){...}
timer.scheduleAtFixedRate(tone, 1000, 1000); //60 BPM. Executes every 1000 ms.
Another possibility that may meet your requirements (from your comments) is spinning a thread and checking System.nanoTime() and sleeping in increments but spinning when you get close to wake up.
long delayNanos = 500000000;
long wakeup = System.nanoTime() + delayNanos; //Half second from right now
long now;
while(!done){
now = System.nanoTime();
//If we are less than 50 milliseconds from wake up. Spin away.
if(now <= wakeup - 50000000){
//Sleep in very small increments, so we don't spin unrestricted.
Thread.sleep(10);
}
if(now >= wakeup){
//Play sound
wakeup += delayNanos;
}
}
When this play sound is called
mSoundManager.playSound(1);
Android waits until that call is finished, then you call
mHandler.postAtTime(this, SystemClock.uptimeMillis() + 200);
however, if you reverse those calls, you may find that the timing is more accurate.
mHandler.postAtTime(this, SystemClock.uptimeMillis() + 200);
mSoundManager.playSound(1);
You can't count on your sound taking exactly the same amount of time to play, so telling the handler to post first is a bit better. Still not ideal, however.