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)
Related
I would like to setup a notification which triggers every 20 seconds. I set an AlarmReceiver in my onCreate() method in my Fragment:
Intent alarmIntent = new Intent(getActivity(), IntentService.AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(getContext(), 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(), 20000, pendingIntent);
In my IntentService class I have the following static class:
public static class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent send = new Intent(context, IntentService.class);
context.startService(send);
}
}
I would like to create my Notification in that IntentService class which I start above.
The AlarmManager works, and it executes in every 20 seconds, but it is also triggered every time when my Fragment created.
My question is: Where/how should I start my AlarmManager to not execute everytime when my Fragement created?
You're not telling the alarm manager to set off the alarm in 20 seconds from now and then every 20 seconds, but now and then every 20 seconds. That's why Android fires the alarm right away - it catches up on past alarms and "now" is some milliseconds past when the code finishes. You need to make sure that the first scheduled alarm is in the future.
So what you really need is this:
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 20000, 20000, pendingIntent);
This tells the alarm manager to schedule the next alarm in 20 seconds, repeating every 20 seconds.
I'm trying to create an Alarm that will fix lost connections to Google Cloud Messaging that occur due to the heartbeat bug, found here How to avoid delay in Android GCM messages / change heartbeat
However, my alarm's onReceive class which I have being set to be called every 1 minute for testing is never being called. I've looked in several of the other questions pertaining to this topic, and all of them concentrate on spelling and declaring the receiver in the manifest, which I've checked several times.
Here is all the relevant code:
MainActivity.java
//Alarm created here
GCMHeartbeatAlarm gcmAlarm = new GCMHeartbeatAlarm();
gcmAlarm.setAlarm(this);
GCMHeartbeatAlarm.java
public class GCMHeartbeatAlarm extends BroadcastReceiver {
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
#Override
public void onReceive(Context context, Intent intent) {
//The part which is supposedly going to fix the GCM connection dropped bug, needs to be called every 5 mins or so via alarm to keep
//GCM connection open
//Commented out for now
// context.sendBroadcast(new Intent("com.google.android.intent.action.GTALK_HEARTBEAT"));
// context.sendBroadcast(new Intent("com.google.android.intent.action.MCS_HEARTBEAT"));
Log.i("GCMHeartbeat", "GCM Heartbeat Sent!");
}
public void setAlarm(Context context) {
alarmMgr=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, GCMHeartbeatAlarm.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
//Repeat every 1 minute
alarmMgr.setRepeating(AlarmManager.ELAPSED_REALTIME, System.currentTimeMillis(), 1000 * 60 * 1 , alarmIntent);
Log.i("GCMHeartbeat", "Alarm set!");
}
}
AndroidManifest.xml
<!-- GCM Heartbeat Alarm Receiver -->
<receiver
android:name="com.MyApp.app.GCMHeartbeatAlarm">
</receiver>
With this code, the "Alarm Set!" log is hit, but the log in onReceive is never hit.
Anything that could help me figure out what's going on would be greatly appreciated!
Got it to work eventually. I'm not quite sure why, but using System.currentTimeMillis() wasn't working for the triggerAtMillis value. Perhaps it was because the alarm was set for ELAPSED_REALTIME instead of currentTimeMillis(), so the first alarm was never triggered. Instead I used SystemClock.elapsedRealtime() + 60 * 1000 to trigger the alarm beginning 1 minute after it is set, and then the onReceive method started being called in 1 minute intervals.
The working code was:
public void setAlarm(Context context) {
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, GCMHeartbeatAlarm.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
alarmMgr.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 60 * 1000, 60 * 1000, alarmIntent);
Log.e("GCMHeartbeat", "Alarm set!");
}
I have set alarm to get trigger after 60 seconds. but the alarm is getting triggered after 80/90 seconds (But not exactly after 60 seconds). How can i set alarm to get trigger exact at specified time?
//calling method to set alarm after 60 seconds
startAlarm(context, 1, System.currentTimeMillis()+60000);
//method defination
public static void startAlarm(Context context, int timerType, long nextScheduledTime) {
EABLog.d(TAG, " ~~~INSIDE START ALARM~~~~~ "+timerType);
Intent intent = new Intent(context, AlarmReceiver.class);
intent.putExtra(Constants.KEY_TIMER_TYPE, timerType);
intent.setAction(""+timerType);
PendingIntent pollPendingIntent = PendingIntent.getBroadcast(context,
timerType, intent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, nextScheduledTime,
pollPendingIntent);
EABLog.d(TAG, System.currentTimeMillis()+" ALARM IS SET AT "+nextScheduledTime+" TYPE :"+timerType);
}
//permission added in Android Manifest
<uses-permission android:name="android.permission.WAKE_LOCK"/>
As docs say about setExact - The alarm will be delivered as nearly as possible to the requested trigger time. So it is not as exact as you think :)
Look at public void setWindow (int type, long windowStartMillis, long windowLengthMillis, PendingIntent operation) methods 3rd parameter - windowLengthMillis The length of the requested delivery window, in milliseconds. The alarm will be delivered no later than this many milliseconds after windowStartMillis.
This might do the trick :)
First off,this site is great and everyone is so helpfull. This is my first post so forgive me if i have ommited anything.
I create an alarm like so:
private void startLocation() {
AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, MyWeatherUpdateService.class);
PendingIntent service = PendingIntent.getService(context, 0, i,
PendingIntent.FLAG_CANCEL_CURRENT);
alarm.setRepeating(AlarmManager.RTC, SystemClock.elapsedRealtime() + (60 * 1000),
Long.parseLong(prefs.getString("listpref", "60000")), service);
}
In this method which is called inside a fragment, context is from getApplication (), listpref is a string update interval in milliseconds.
I cancel it by:
public void endLocation() {
Intent i = new Intent(context, MyWeatherUpdateService.class);
PendingIntent service = PendingIntent.getService(context, 0, i,
PendingIntent.FLAG_CANCEL_CURRENT);
alarm.cancel(service);
}
Ensuring that the intent/pending intent is the same.
Now i have 2 issues:
1) the alarm fires almost imediately after creation, even though i tell it to start after 1min.
2) when i call cancel, the alarm fires once more before the alarm is cancelled.
With question 1) why does the alarm fire so soon? And with 2) is this working as intended or should the alarm cancel immediately like i want it to.
If i have not supplied enough info, ill add more code if required.
Thanks in advance.
the alarm fires almost imediately after creation, even though i tell it to start after 1min
That is because you are using RTC with an elapsedRealtime() starting time. Those need to match. The simplest solution is to switch to ELAPSED_REALTIME.
when i call cancel, the alarm fires once more before the alarm is cancelled.
Try replacing PendingIntent.FLAG_CANCEL_CURRENT with 0, at least in the PendingIntent for your cancel() call.
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.