In order to implement a reminder, I need to set a memo like: "starting from today, show a memo, each friday, one week yes and one no"
So, I think I can determin for each memo, what is the next date I have to show it. And then pass this date to a Timer like this:
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
//show my memo
});
}}, date); //
Supposing now is Mon 26/11/2012 how can I determine when occurs the first friday (according to the aforementioned memo?
I'm not sure this mechanism is enough good, if someone can suggest me another approch I would be grateful.
Timer is not a good class to use for this. You should take a look at AlarmManager and schedule your events using that.
You can use AlarmManager.set() to set a specific alarm, AlarmManager.setInexactRepeating() to set a repeating alarm that has some flexibility in terms of exactness, setRepeating() to set a precise repeating alarm.
In all cases you set up a PendingIntent that gets launched when the alarm fires, and your application should be prepared to handle that intent correctly.
Remember that you don't necessarily need to take action when that PendingIntent is fired: you can just check if the conditions are right (for example, you can add some logic as to whether the user should be notified or not at that point).
More about AlarmManager and PendingIntent:
http://developer.android.com/reference/android/app/AlarmManager.html
http://developer.android.com/reference/android/app/PendingIntent.html
Also, remember that you have to add a broadcast receiver to the "boot sequence completed" event so that you can reinstall your alarms after the device has been rebooted, since alarms don't persist across reboots.
Related
In my app, I want to kick off an timer that triggers an action every x minutes, regardless if the user is currently in the app or not. I have been reading around and am not sure which combo of Broadcast and Receiver types I should use - any guidance would be helpful.
Example of user actions:
User hits a button, sets initial timer (alarm)
Timer is reached, trigger an action and set the timer again
Repeat until it has run for x minutes
when the user hits button set alarm as
AlarmManager am = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
am.setRepeating (AlarmManager.Type,
long triggeringtime,
long interval,
PendingIntent operation);
here triggeringtime is how to time it shud take to take an action
and interval how to much time it would take to do the same.
here operation is the Intent which you need to execute like it may be an activity or Service you can Define it as
operation = PendingIntent.getActivity( context, 0, intent or service, 0);
2 and 3 step will be continuously run thats what the alarm manager does.
This alarm continues repeating until explicitly removed with
cancel(AlarmManager.OnAlarmListener).
I am a beginner Sry if i wrong. Hope it helps!
Android JobScheduler
You can find a lot of tutorial online.
I need to set Alarm on 9.00 AM, 11 AM and 1PM in everyday.
Simple solution is to use three different pending Intent but Is it any other way to implement same with one pending Intent?
Thanks in Advance!
Thanks, Got solution
Only need to change request code in same Intent. It will not cancel previous alarm. Click Here for solution
If you have a limited number of alarms that at any time need to be scheduled, maybe use one PendingIntent for each alarm can be fine.
However if you have a potentially unlimited (or maybe just a lot) number of alarms to be scheduled, I think that a better approch can be to provide a scheduler that can act over the scheduling information. For example, if you need to create something like a calendar where you can set one or more Event for each day, you should consider this approch.
You can take a look at the Alarm section of tha Android Calendar project
As you can see there is a class named AlarmScheduler in which you have a method
void scheduleNextAlarm(Context context, AlarmManagerInterface alarmManager,
int batchSize, long currentMillis)
That determines the next alarm that need to be scheduled.
In the specific implementation you can see that the method calls another method:
queryUpcomingEvents()
that operates over a content provider (Calendar provider) and gets the upcoming events.
Each time you trigger a new Alarm you can reschedule a new one, looking in the content provider (or wherever you store your scheduling information), or you can applay different scheduling policiy. For example if an user create a new remider for an Event on the calendar you need to reschedule the alarms (for example you could decide to schedule all the alarms for today, or just the next alarm).
In my applications I usually use the following code (inside the onReceive() of the BroadcastReceiver that is triggered when the alarm fires):
private void restartScheduler(Context context){
Intent t = new Intent("it.gvillani.socialapp.alerts.SCHEDULE_REQUEST");
context.sendBroadcast(t);
}
And then of course I have a BroadcastReceiver that waits for that action and try to reschedule the alarms:
public class SchedulerReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context c, Intent intent) {
if (intent.getAction().equals("it.gvillani.socialapp.alerts.SCHEDULE_REQUEST")) {
startScheduler(c);
}
}
private void startScheduler(Context c) {
AlarmScheduler.clearAlarms(c);
AlarmScheduler.scheduleNextAlarm(c);
}
}
I want to create a scheduler for my app. My current idea is to create a background service which starts up on boot and listens to the date and time. This triggers my application. But I'm guessing this isn't the most efficient method. I googled quite extensively and didn't come up with anything different. Is there a more efficient way than creating a service?
[EDIT]
Making my question clearer. I'd like to make something like this.
Say I want to run the app every Monday at 10:00am how would I go about doing that? The method I concocted or something more efficient?
All you need is the system's AlarmManager in conjunction with a BroadcastReceiver which starts an IntentService.
Update: On second read, what do you mean by trigger my application? I was assuming it's non-interactive, but if it is interactive, you could bring up your Activity with the help of the BroadcastReceiver; no IntentService required then. Saves you the time monitoring either way.
Update One of the central questions you have to ask yourself is, do I want to wake up the device, such that my {app, service} is run exactly at that point in time, or is it okay to have that run immediately after the device is woken up by the user, if "another Monday 10oo am" has passed by?
Regardless of the answer to that question, you'll use the system's AlarmManager to set up a repeating alarm, either with setRepeating() or setInexactRepeating(), and with either RTC or RTC_WAKEUP. triggerAtMillis is the time delta to the next Monday 10oo am and intervalMillis is the number of milliseconds which a week has.
And that's it.
I think you need to fix the schedule of your code..
Try this code for schedule the particular functionality..
Timer mTimer = new Timer();
TimerTask mTimerTask = new TimerTask() {
#Override
public void run() {
/*your code here..*/
}
};
mTimer.scheduleAtFixedRate(mTimerTask, getTomorrowMorning2AM(), 1000*60*60*24);
}
private static java.util.Date getTomorrowMorning2AM(){
Calendar c = Calendar.getInstance();
java.util.Date date2am = c.getTime();
date2am.setHours(2);
date2am.setMinutes(0);
return date2am;
}
I am building a reminder application where the user enters an event into an SQLite DB. The main screen lists the title of each reminder and clicking an item shows the details of it. All of this works fine.
Now I want to allow the user to set up notifications for each item, being given an option to set a reminder for 15 mins, 30 mins, or 1hr before the event is scheduled.
I have no clue how to go about this and can't find any good tutorial on it. Can anyone give me some idea as to how I might implement this?
Thanks!
Use the AlaramManager to fire a broadcast that will tell your app to show a notification to the user about the event.
Here is an example of using it: Alarm Manager Example
Once you get the date of the event from the database, it's as easy as any other notification, just keep in mind that you'd subtract the amount of time (the 15,30,60 minutes) to the date.
Timer timer = new Timer();
SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy HH:mm");
Date date = formatter.parse("11/08/2012 16:39");
timer.schedule(timerTask, date);
This will schedule the event to the event time, and I'm understanding you want a reminder before the event actually happens. To do this you can create a calendar object to modify the date in the means you need. Remember to remove the previous schedule or you will be left with two reminders (one at the time, and one as a reminder).
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.MINUTE, -15);//Or whatever
//Then schedule it.
time.schedule(timerTask,cal.getTime());
Both approaches are using the variable timerTask which could be something like this, involving the createNotification method call that will in fact create the pending notification.
TimerTask timerTask = new TimerTask(){
#Override
public void run(){
createNotification(title, text, tickerText, millisec);
}
};
There is a potential issue with this thou. If the application is closed, I believe the timer dies with it, so depending on the nature of your application you may want to use the AlarmManager as others have suggested.
You'll use the AlarmManager to set the action to be triggered on the specific date/time. (there're A LOT of tutorials on how to use the AlarmManager)
The alarm manager event always triggers a PendingIntent. From this intent you can either make a broadcast or start a service. (you'll have to create a broadcast receiver or a service)
Then on the broadcast receiver or service you build up and show the notification.
I suggest the broadcast receiver route, it's cleaner and more seamless.
you might also to have a broadcast receiver for onBoot events to re-schedule the events on the alarm manager case the user reboots the device.
I want to send data to server at some regular interval. So, I am using AlarmManager for the same. It works fine but the problem is that when I cancel the Alarm on Date/Time change. At that time Alarm fires again before getting cancelled, so that makes my application worse as an extra data is sent to server with irregular interval.
Here is my BroadCastReceiver class with AlarmManager.
public class MyReceiver extends BroadcastReceiver{
AlarmManager mgr;
PendingIntent pi;
Intent intent;
public static boolean flag = false;
#Override
public void onReceive(final Context arg0, Intent arg1) {
if(arg1.getAction().equals("android.intent.action.TIME_SET")){
Log.d("MyReceiver", "Time set");
mgr = (AlarmManager) arg0.getSystemService(Context.ALARM_SERVICE);
intent = new Intent(arg0, TestService.class);
intent.putExtra("test", "testvalue");
pi = PendingIntent.getService(arg0, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
if(!flag){
mgr.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 10000, 5000, pi);
flag = true;
}
else{
mgr.cancel(pi);
pi.cancel();
flag = false;
}
}
}
}
Below is the Screen Shot with Logcat output that explains that after cancelling the Alarm it fires once more time just after cancelling.
As you can see in the Logcat output black arrow shows where I changed that time to cancel the Alarm and red arrow shows that after cancelling the Alarm once again it fired just before cancelling which should not happen. So, can anyone give my idea why that is happening and what should I do to restrict Alarm getting fired again before cancelling.
NOTE:- This only happens when I tried to increase date/time say from 10:00 to 11:00, works perfect when I decrease time say 10:00 to 9:00.
Not able to see the LogCat at my end, but looking at the code, I am not sure, how is the Service which gets invoked (TestService) gets killed / stopped ? I think you would need to stop it somehow. Also, its not recommended to do long running tasks within the broadcast receiver.
Have you verified that you service stop event is occuring after the mgr.cancel(pi) is fired?
Just try with some unique code with pending intent within activity and then cancel that intent using the same code.
setting pending intent in activity
PendingIntent.getBroadcast(this, code, intent, PendingIntent.FLAG_UPDATE_CURRENT);
for stopping that broadcast receiver
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), code, intent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
why that is happening
First Thing is that you are using Intent Action android.intent.action.TIME_SET so It does mean that Everytime any how if the System date/time gets Changed your BroadcastReceiver will ne called Automatically.
Second you have used one static boolean flag in your Receiver class.
Now what is happening is Whenever you change your System timings the flag toggles it's state from false to true and from true to false.
That is what exactly happening in your code and logcat also shows the same that everything is working as per the code written.
So according to me there is nothing Wrong happening in the code and it's output.
what should I do to restrict Alarm getting fired again before cancelling
First thing as I think, you should not use Action TIME_SET like that to toggle flag on/off as users and developers might not remember for what they are changing time either to turn FLAG On or Off,
Better way is that,
you should handle the Service yourself by an Activity and show one ToggleButton there to manage the State of the FLAG and set and cancel the PendingIntent.
OR
And If you want to do the task of your service automatically then you just simply use the AlarmManager and set your Alarm Triggering time and Interval there only once say time is currenttime and Interval is 50000 miliseconds..
so it will obviously call the service from now onwards after every 5mins, then in your App you will only require one ToggelButton to indciate the Sync to ther server is On or Off , if user Toggle it on or off then write your AlarmManager code there in your Activity only in the toggleButtontb.setOnCheckedChangeListener(listener) , I suppose this is the better way then what you are actually implementing.
I don't understand what need to set the receiver for date change if your goal is only to send the data on server in some regular interval .
change date and time of device does not mean that your alarm wont work
at that time which you already have set before those changes .Alarmmanager work on that given duration of time which is excluding from local current date and time of device .