I changed AlarmController.java in ApiDemo a little bit, so I want the alarm not to go off when the phone is sleeping by using AlarmManager.RTC.
Intent intent = new Intent(AlarmController.this, RepeatingAlarm.class);
PendingIntent sender = PendingIntent.getBroadcast(AlarmController.this,
0, intent, 0);
// We want the alarm to go off 30 seconds from now.
long firstTime = SystemClock.elapsedRealtime();
firstTime += 15*1000;
// Schedule the alarm!
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC, //AlarmManager.ELAPSED_REALTIME_WAKEUP,
firstTime, 15*1000, sender);
The receiver code is like below:
public class RepeatingAlarm extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Log.d("DEBUG", "In RepeatingAlarm.onReceive, intent=" + intent);
Toast.makeText(context, R.string.repeating_received, Toast.LENGTH_SHORT).show();
}
}
I ran the modified app, but I still see many log messages as below after the phone wento sleep (the screen was black):
D/DEBUG ( 1390): In RepeatingAlarm.onReceive, intent=Intent { flg=0x4 cmp=com.example.android.apis/.app.RepeatingAlarm (has extras) }
This means the flag AlarmManager.RTC didn't work. Can someone tell me why?
Thanks.
Since you are using elapsedRealtime to get the alarm start time, I think you need to use the ELAPSED_REALTIME flag instead of the RTC flag.
My guess is that the alarm manager is thinking it's missed a ton of alarms because you are using the RTC flag which means the alarm manager is expecting you to send a time value in milliseconds since Jan 1st 1970, but instead you are sending elapsed milliseconds since the device booted, which is going to be a much much smaller number.
If you use the RTC flags you need to use System.currentTimeMillis() or get the time in milliseconds from a Java Date or Calendar object. If you use ELAPSED_REALTIME flags then you need to use SystemClock.elapsedRealtime().
Related
Currently I'm working on a new android project which uses background service. Because android version >=Oreo kills service automatically. So i use AlarmManager. I need to display a notification on exact time. Time for notification is setted in shared preferences.
My Alarm handler is following
class AlarmHandler {
private Context context;
AlarmHandler(Context context){
this.context=context;
}
void setAlarmManager(){
Intent intent=new Intent(context,NotificationService.class);
PendingIntent pendingIntent=PendingIntent.getBroadcast(context,2,intent,0);
AlarmManager alarmManager= (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if(alarmManager!=null){
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,5000,60000,pendingIntent);
}
}
void cancelAlarmManager(){
Intent intent=new Intent(context,NotificationService.class);
PendingIntent pendingIntent=PendingIntent.getBroadcast(context,2,intent,0);
AlarmManager alarmManager= (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if(alarmManager!=null){
alarmManager.cancel(pendingIntent);
}
}
}
My Notification service is following
public class NotificationService extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String t1=timeFromsharedPreferences("t1");
String t2=timeFromsharedPreferences("t2");
String systemTime=getCurrentTime();
if(systemTime.equals(t1)){
notify();
}else if(systemTime.equals(t2)){
notify();
}
}
}
I start AlarmHandler using following code
AlarmHandler alarmHandler=new AlarmHandler(this);
alarmHandler.cancelAlarmManager();
alarmHandler.setAlarmManager();
I also register the broad cast receiver as following
<receiver android:name=".NotificationService" android:enabled="true" />
My problem is some times it's skipping my notification. Time is sheduled for 10:00 pm and 7:00 am. Notification on 10 pm is recieved (Note that i'm using phone at 10:00 pm or used minutes before 10:00 pm). But notification on 7:00 am is not receiving all time. Also note that i need notification on every day at same times. Please help me.
You cannot have a repeating exact alarm. If you need it to repeat at exact intervals, you need to set an exact alarm at the 1st interval, then re-arm the alarm when it fires so it is armed for the next interval, and keep repeating that process.
Edit:
you need to do something like this
1.- compute delta in millis to next interval
2.- set exact alarm to fire in delta millis
3.- when the alarm fires, handle the event and then go to step 1
I am have been reading over this tutorial for creating repeating apps:
http://rdyonline.net/android-bytes-alarms/
I have followed the instructions and it is working beautifully. However I don't like using something if I don't understand how it works.
Alarm manager is using an version >= 19 so instead of alarm repeating (exact) it requires a one off alarm that is reset on exiting the intent.
Now as I said it is working, Every 15 minutes it is going off (in my version). I can see that they are bundling data with the intent, but I really have no understanding what is re-triggering the single shot alarm.
This is their code:
Repeating alarms
If you’re targeting any Android version before API 19 (KitKat), or,
you don’t need them to be exact then repeating alarms are nice and
easy. All you need in this case is to use the setRepeating call.
In some cases, it will be important that you set a repeating alarm
that is accurate, I’ll go in to a little more detail on how to handle
this.
The trick here is to make sure you schedule the next alarm once the
previous alarm goes off. You’ll have to check whether the alarm you
have set is intended to be repeated and also make sure the platform
you’re running on is above API 19
#Override
public void onReceive(android.content.Context context,
android.content.Intent intent) {
WrappedAlarmManager am = new WrappedAlarmManager(context);
Bundle extras = intent.getExtras();
if (am.isSingleAlarm(extras)) {
Toast.makeText(context, "Single alarm", Toast.LENGTH_SHORT).show();
} else if (am.isRepeatAlarm(extras)) {
Toast.makeText(context, "Repeat alarm", Toast.LENGTH_SHORT).show();
if (android.os.Build.VERSION.SDK_INT >= 19) {
am.scheduleRepeatingAlarm(context);
}
}
}
A quick check to see if it’s a repeating alarm and then the repeating
alarm is scheduled again. Below are the two pertinent methods to deal
with this logic:
public boolean isRepeatAlarm(Bundle extras) {
return extras.containsKey(KEY_REPEAT) && extras.getBoolean(KEY_REPEAT);
}
public void scheduleRepeatingAlarm(Context context) {
Intent intent = new Intent(context, NotificationReceiver.class);
Bundle extras = new Bundle();
extras.putBoolean(KEY_REPEAT, true);
intent.putExtras(extras);
PendingIntent pIntent = PendingIntent.getBroadcast(context,
REPEAT_ALARM_ID, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Calendar futureDate = Calendar.getInstance();
futureDate.add(Calendar.SECOND, (int) (INTERVAL_SEVEN_SECONDS / 1000));
if (android.os.Build.VERSION.SDK_INT >= 19) {
setSingleExactAlarm(futureDate.getTime().getTime(), pIntent);
} else {
mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, futureDate
.getTime().getTime(), INTERVAL_SEVEN_SECONDS, pIntent);
}
}
Thanks for your help
To schedule a repeating alarm in SDK versions >= 19, when alarm broadcast is received , the boolean value KEY_REPEAT is checked and if it is true then a single exact alarm is scheduled for INTERVAL_SEVEN_SECONDS / 1000 seconds later.
After INTERVAL_SEVEN_SECONDS / 1000 seconds later the broadcast is again received and next alram is set.
This receiving broadcast and scheduling next alarm cycle repeats continuously.
The code for setting the alarm is:
mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), interval, getPendingIntent());
I tried also
mAlarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, cal.getTimeInMillis(), interval, getPendingIntent());
Where
interval = type long of ~60000
cal = Calendar.getInstance() then modified DAY, HOUR etc.
I've noticed that my alarm doesn't trigger if phone in deep sleep at all.
I also checked command
adb shell dumpsys alarm
And alarm is written in and should start at time selected. Where's the catch then that alarm sometimes does, sometimes doesn't trigger?
BroadcastReceiver works as it should since i'm logging other possible actions too:
public class Receiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// some things here...
}
}
AndroidManifest.xml includes permissions for:
android.alarm.permission.SET_ALARM
This is really confusing and Serious issue for my app...
i have setting repeated alarm manager to start service which fetch the location and send SMS but currently i am only writing time duration in file to check the alarm accuracy .
I find that the alarm manager not working fine , i set for one hours interval but it fired at 30 min. interval . I left it for a day and find that after 12'o clock the alarm accuracy is right. What happening ??
My Activity class which start alarm :
enter code here
public static final long ALARM_TRIGGER_AT_TIME = SystemClock.elapsedRealtime() + 20000;
public static final long ALARM_INTERVAL = 1000 * 60 * 60 ;
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Intent myIntent = new Intent(AutoMainActivity.this, TrackerService.class);
pendingIntent = PendingIntent.getService(AutoMainActivity.this, 0, myIntent, 0);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,ALARM_TRIGGER_AT_TIME, 1000 * 60 * 60,pendingIntent);
AND my service class :
TraceService :
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
//writing in file to view time
java.util.Date systemDates = Calendar.getInstance().getTime();
simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss");
currentTime = simpleDateFormat.format(systemDates);
// create file and write current time
generateNoteOnSD("ONSTART"+currentTime+"\n","Onstart.txt");
}
After executing this apps at 3:18 PM time .The file created by service show the alarm time . Check this :
alarm manager time
ONSTART2013-05-13-15:18:26
ONSTART2013-05-13-15:21:58
ONSTART2013-05-13-15:54:21
ONSTART2013-05-13-16:18:25
ONSTART2013-05-13-17:18:26
ONSTART2013-05-13-17:49:21
ONSTART2013-05-13-18:18:25
ONSTART2013-05-13-19:18:28
ONSTART2013-05-13-20:10:51
ONSTART2013-05-13-20:18:29
ONSTART2013-05-13-20:48:49
ONSTART2013-05-13-21:18:30
ONSTART2013-05-13-21:58:58
ONSTART2013-05-13-22:18:38
ONSTART2013-05-13-22:56:00
ONSTART2013-05-13-23:18:43
ONSTART2013-05-13-23:48:49
ONSTART2013-05-14-00:18:44
ONSTART2013-05-14-01:18:45
ONSTART2013-05-14-02:18:45
ONSTART2013-05-14-03:18:45
ONSTART2013-05-14-04:18:45
ONSTART2013-05-14-05:18:44
ONSTART2013-05-14-06:18:44
ONSTART2013-05-14-07:18:44
You can check that when alarm manager start at 15:18 PM , it start again after 30 min. approx. But after 12'o clock it work fine !!! How to fix it. I need that alarm start every one hour not before that .
Try with AlarmManager.RTC_WAKEUP once instead of AlarmManager.ELAPSED_REALTIME_WAKEUP
There is an example in this : Alarm Manager Example
I suspect that you have multiple alarms pending. I would recommend that you clear out all of your alarms before you set this one.
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
// Cancel alarms
try {
alarmManager.cancel(intent);
} catch (Exception e) {
Log.e(TAG, "AlarmManager update was not canceled. " + e.toString());
}
}
(how to cancel alarms is answered well in this answer)
Not sure why everyone complicates this issue so much. I'm seeing it everywhere. Answers and answers about calculating the next hour.
There's absolutely no need to calculate anything. The the HOUR from the Calender and use that as the interval. The HOUR is called everytime the hour changes. That's all there really is to it.
Some devices may need a little tweaking to make sure the HOUR being called is not the same one for consecutive times. This is due to some devices calling the HOUR sometimes when the minute changes.
In my app, I use the AlarmManager class to set an alarm. To trigger the alarm after the mobile is rebooted I have used BroadcastReceiver. All works fine and my alarm is triggered at regular intervals. Now the problem arises in this case :
Suppose my current time is 2:30 pm and I set my alarm at 2:35 pm. After that, I switch off the mobile. After an hour when I switch on my mobile, no alarm is pop-up as the time on which the alarm is set. This is happening because the current time exceeds the time on which I set the alarm. To solve this issue what should I do. I have posted my code for setting alarm in the AlarmManager class. Please help me to solve this out
public class AlarmReceiver extends BroadcastReceiver {
#SuppressWarnings("static-access")
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
Intent myIntent = new Intent(context, MyAlarmService.class);
PendingIntent pendingIntent = PendingIntent.getService(context, i, myIntent, i);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.MILLISECOND, (int) Utilities.diff(NoteManager.getSingletonObject().getAlarmTime(i)));
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
}
}
public static long diff(Date date) {
long difference = 0;
try {
// set current time
Calendar c = Calendar.getInstance();
difference = date.getTime() - c.getTimeInMillis();
if (difference < 0) {
// if difference is -1 - means alarm time is of previous time then current
// then firstly change it to +positive and subtract form 86400000 to get exact new time to play alarm
// 86400000-Total no of milliseconds of 24hr Day
difference = difference * -1;
difference = 86400000 - difference;
}
}
catch (Exception e) {
e.printStackTrace();
}
return difference;
}
In The Manifest File
<receiver android:name=".AlarmReciever">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
better way is to store that alarm details in database and retrieve it on boot via broadcast receiver as you are saying you implemented one. once notified remove the details from the database. this way u can track all your alarms. even you can start a Service on startup and do this operation
The Alarm app in the Android does the same, if your phone is switched off and there is Alarm to ring up, It will make your phone switch On , ring the alarm and go to sleep again.
Here is the link of source of Alarm app Git_Alarm app you can download it and see how it is doing this.
and if you are doing something else in your alarm reciever then to ring Alarm up. you can basically set alarmreciever again in the phone Boot up, here is the one answer which may help you Alarm problem if phone is switched off
Edit :- one link was broken, replaced it