start repeating alarm from AlarmManager - android

I want to start a service every day from 8am to 6pm. I am using 3 alarms.
For starting alarm2 everyday at 8am.
For starting service every 1 min.
To stop alarm2.
Is it the proper way? Also I am unable to start alarm2 from alarm1.
This is code for alarm 1:
public class AlarmReceiver1 extends BroadcastReceiver {
int interval;
#Override
public void onReceive(Context context, Intent intent) {
AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent in=new Intent(this,AlarmReceiver2);
PendingIntent startingIntent = PendingIntent.getBroadcast(context, 0,in, 0);
long duration = interval * 60 * 1000;
manager.setRepeating(AlarmManager.RTC_WAKEUP,timeOn.getTimeInMillis(), 86400000,startingIntent);
}
}

Far from enough code to tell if it has been set up properly. There is a good example here on how you should set up the AlarmManager. I'd recommend looking it through if there is something you've missed.
Also as you can see in the example you gotta reset the Alarms every time the phone is rebooted. If you don't the services will not run.

Related

Alarm Manager is sometimes very long to run the intent

I got a problem with the AlarmManager. When the alarm is set, if the alarm's hour has already passed the intent is started which is great. But sometimes there is a very long time (from 30 secondes to 3 minutes) before the intent is started. If anyone knows why, I'm curious to understand.
Here is my code :
public static void setAlarm()
{
Intent intent = new Intent(Application.Context, typeof(AlarmReceiver));
intent.SetAction("ExchangeGo");
PendingIntent pendingIntent = PendingIntent.GetBroadcast(Application.Context, 0, intent, PendingIntentFlags.CancelCurrent);
Calendar dayCalendar = Calendar.GetInstance(Java.Util.TimeZone.Default);
dayCalendar.Set(CalendarField.HourOfDay, 8);
dayCalendar.Set(CalendarField.Minute, 30);
dayCalendar.Set(CalendarField.Second, 0);
dayCalendar.Set(CalendarField.Millisecond, 0);
AlarmManager alarm = Application.Context.GetSystemService(Context.AlarmService).JavaCast<AlarmManager>();
alarm.Cancel(pendingIntent);
alarm.SetRepeating(AlarmType.RtcWakeup, dayCalendar.TimeInMillis, AlarmManager.IntervalDay, pendingIntent);
}
And here the intent :
[BroadcastReceiver]
public class AlarmReceiver : BroadcastReceiver
{
private String SOMEACTION = "ExchangeGo";
public override void OnReceive(Context context, Intent intent)
{
String action = intent.Action;
if (SOMEACTION.Equals(action))
{
Intent intentService = new Intent(context, typeof(ExchangeService2));
context.StartService(intentService);
}
}
}
There is no problem with manifest cause it works, just a bit too long sometimes. And the problem is not from my second intent because I put a breakPoint just before and the waiting time is before the break point.
Anyone ?
Thanks for reading me.
As setRepeating() doesn't guarantee that it will happen at precise time.
That's why you are getting delay of 30 secondes to 3 minutes.
Replace setRepeating() with setExact() refer documentation from Here
manager.setExact(AlarmManager.RTC, startTime.getTimeInMillis(), operation);
To repeat this what you can do is, to schedule this alarm again after executing your current event. So when your 1st intent gets executed schedule alarm for 2nd event using setExact() only. This will guarantee the time accuracy you are expecting

how to set an Ending Point for Alarm Manager

I have an Alarm Manager that runs periodically , but I want to have a specific set of time that it will be running. For Example , lets say that we have a periodic Alarm Manager that is registered with a broadcast receiver and an Action is being performed every 30 minutes. The thing is that I want the Alarm Manager to be active for a specific time lets say 3 hours, so the Alarm manager should goes off 3 hours / 30 minutes or 6 times.
Code to start the define the Alarm Manager:
TimerPeriodic = (AlarmManager)getActivity().getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(getActivity(),AlarmReceiver.class);
intent.putExtra(Constants.ALARM_ID, Constants.TIMER_PERIODIC_ID);
TimerPeriodicPendingIntent = PendingIntent.getBroadcast(getActivity(), 0, intent, 0);
Fire Alarm Manager:
long start = TimeUnit.MINUTES.toMillis(StartMinutes);
TimerPeriodic.setRepeating(
AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + start, start, TimerPeriodicPendingIntent);
Also the alarm Manager should be active if the Application is killed.
Thank you for any help!
It can be acheived by using Sqlite Db. where you store the Alaram ID,count,and repeation (How many time you want to repeat).
when Alarm is trigger (AlarmReceiver.onReceive()) increment the count check with the condition with repeation. if it exceed just cancel it. Hope It will help :)
#Override
public void onReceive(Context context, Intent intent) {
AlarmManager alarmManager = (AlarmManager) context.getApplicationContext().getSystemService(
context.ALARM_SERVICE);
Intent myIntent = new Intent(context, AlarmReceiver.class);
cancelAlarm(reminder.getId(),myIntent,alarmManager);
}
private void cancelAlarm(int notiId,Intent myIntent,AlarmManager alarmManager) {
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, notiId, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.cancel(pendingIntent);
}

How to cancel and set AlarmManager at the same time

What I am doing at the moment is, using AlarmManager.SetAlarm(context) to enable and AlarmManager.CancelAlarm(context) to cancel it. I am using it with an IntentService.
What I want to do is cancel the alarm from triggered IntentService and then set it again such as:
#Override
protected void onHandleIntent(Intent intent) {
FooAlarmManager foo = new FooAlarmManager();
foo.CancelAlarm(FooClass.this);
//Do some stuff
foo.SetAlarm(FooClass.this);
}
Why I am doing this? Because within FooAlarmManager I am getting the time from a static class such as:
public void SetAlarm(Context context) {
Integer minutes = StaticValuePass.getMins();
AlarmManager am = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, FooAlarmManager.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
am.setInexactRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(), 1000 * minutes*60, pi);
}
And I am setting the value of time from onHandleIntent(). So basically I am doing some check within onHandleIntent() and determining when should be the next alarm.
Unfortunetely, my code above doesn't work, the reason is when you use setAlarm() it actually invokes onHandleIntent() immediately.
So I have two questions in this case,
1) Can I prevent setAlarm() to invoke onHandleIntent() when it is firstly created?
2) (Assuming the above doesn't work) How can I change the alarm interval time?
The second parameter, currently System.currentTimeMillis(), is the time at which you want the repeating alarm to first go off. So setting it to the current time will trigger the alarm immediately. Setting it to System.currentTimeMillis() + (1000 * minutes * 60) should fix your problem.
Please refer to the documentation: https://developer.android.com/reference/android/app/AlarmManager.html#setInexactRepeating(int,+long,+long,+android.app.PendingIntent)

Modifying Alarms Which Trigger Services Based on Screen Status

I am currently starting a service using a Broadcast Receiver which fires 60 seconds after the device boots up. This broadcast receiver triggers an alarm so that my service runs every 60 seconds. Code for this is as follows:
public class ScheduleReceiver extends BroadcastReceiver {
// Restart service every 60 seconds
private static final long REPEAT_TIME = 1000 * 60;
#Override
public void onReceive(Context context, Intent intent) {
AlarmManager service = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, StartServiceReceiver.class);
PendingIntent pending = PendingIntent.getBroadcast(context, 0, i,PendingIntent.FLAG_CANCEL_CURRENT);
Calendar cal = Calendar.getInstance();
// Start 60 seconds after boot completed
cal.add(Calendar.SECOND, 60);
// Fetch every 60 seconds
// InexactRepeating allows Android to optimize the energy consumption
service.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), REPEAT_TIME, pending);
}
}
The above starts the service as follows:
public class StartServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, PhotoService.class);
context.startService(service);
}
}
I would like to somehow modify this so that my service runs every 60 seconds when the phone screen is on and every 20 minutes when off.
What is the best way to do this ? Can I modify the alarm dynamically when the screen is switched off/on ?
Thanks for any help,
Regards,
Fido
Okay I have found out how to do this so I thought I would put this here in case anyone else is ever curious. (More elegant solutions are always welcome):
First thing is that in my service I added the following to the OnCreate:
#Override
public void onCreate() {
super.onCreate();
// REGISTER RECEIVER THAT HANDLES SCREEN ON AND SCREEN OFF LOGIC
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mReceiver = new ScheduleReceiver();
registerReceiver(mReceiver, filter);
}
This is done so that my broadcast receiver can handle those events. Apparently you cannot register these via intent-filters in the xml.
This means that when the service is created it ensures that these additional system actions can be handled.
I then modified my broadcast receiver to be:
public class ScheduleReceiver extends BroadcastReceiver {
private static final int ALARM_ID = 909;
#Override
public void onReceive(Context context, Intent intent) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
AlarmManager service = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, StartServiceReceiver.class);
PendingIntent pending = PendingIntent.getBroadcast(context, ALARM_ID, i,PendingIntent.FLAG_CANCEL_CURRENT);
service.cancel(pending);
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 60); //Delay startup by one minute - This is useful to prevent over utilization of resources at boot
// Start alarm. Set a long repeat time if the screen is off and a short repeat time if the screen is on
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON) || intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
service.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 60000, pending);
}
else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)){
service.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 600000, pending);
}
}
}
From the above I cancel any current alarms with the same pending intent and then I set a new alarm whenever the screen if switched off/on.
This seems to be working for me. As always any improvements are very welcome.

Update service on boot with timer/alarmclock

I have an update service that starts at boot. The thing is I want it to make a check and then wait for a period of time and restart itself. I did this with alarm clock when my service was tied to an application but now it is independent and I only use a broadcast receiver to start it at boot. The problem is that now for some reason I can't integrate my alarm clock with it.
I only have my UpdateService class and my broadcastreceiver class.My code so far in the broadcastreceiver is this, but I want to put the alarm clock here to say schedule the service to start every 30 seconds. I really need this.
#Override
public void onReceive(Context context, Intent intent) {
Intent startServiceIntent = new Intent(context, UpdateService.class);
context.startService(startServiceIntent);
}
Any suggestions are welcome. Thanks in advance.
I found the answer to my problem:
private boolean service_started=false;
private PendingIntent mAlarmSender;
#Override
public void onReceive(Context context, Intent intent) {
if(!service_started){
// Create an IntentSender that will launch our service, to be scheduled
// with the alarm manager.
mAlarmSender = PendingIntent.getService(context,
0, new Intent(context, UpdateService.class), 0);
//We want the alarm to go off 30 secs from now.
long firstTime = SystemClock.elapsedRealtime();
// Schedule the alarm!
AlarmManager am = (AlarmManager)context.getSystemService(context.ALARM_SERVICE);
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
firstTime,30*1000, mAlarmSender);
service_started=true;
}
}
Eventually,my problem was that I didn't get the context right as follows:
(AlarmManager)getSystemService(ALARM_SERVICE);
changed to
(AlarmManager)context.getSystemService(context.ALARM_SERVICE);

Categories

Resources