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...
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
public void runSound(){
Intent it = new Intent(Values.TAG_EXECUTE_ALARM);
PendingIntent pendIntent = PendingIntent.getBroadcast(this, 0, it, 0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND,0);
AlarmManager alarm = (AlarmManager) getSystemService(ALARM_SERVICE);
long time = calendar.getTimeInMillis();
alarm.set(AlarmManager.RTC_WAKEUP,time,pendIntent);
}
This method is called from a service. My service is supposed to play a sound to notify the user even if the device is on sleep mode.
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent arg1) {
MediaPlayer player = MediaPlayer.create(arg0, R.raw.order_alarm);
player.setAudioStreamType(AudioManager.STREAM_ALARM);
player.start();
}
This is the class that will actually play the sound. Unfortunately the devices doesn't wake up and the sound is not played. When runSound is called before the device enters in sleep mode the sound works perfecly... Any ideas?
Edit:
-> Removed static references (yes, they were dumb, since runSound is inside a service).
-> Yes, the tag value is defined in receiver intent-filter
-> Improved the question.
Well, I cant test now, but looking at your code I can see some problems.
At getBroadcast(), the last parameter has to be a flag, like "FLAG_CANCEL_CURRENT", and I am not sure if 0 is a valid flag.
And at "long time = calendar.getTimeInMillis();" it looks like you are putting a time in the past, well if it is in the past, it will not run, try add 5000 (5s).
All others things looks fine to me.
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
I have set a AlarmManager which will give alarm repeatedly after certain time. I used following code for that.
Intent intent = new Intent(ViewDoughnut.this, NotificationMessage.class);
PendingIntent sender = PendingIntent.getBroadcast(ViewDoughnut.this, 0, intent,PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP,nextAlarmTime, alarmInterval, sender);
Now to execute proper work at the alarm time I have created the following class extending BroadcastReceiver. Now I need the time in millisecond when the Alarm work should execute in that class. How to get it?
public class NotificationMessage extends BroadcastReceiver {
// Display an alert that we've received a message.
// #Override
public void onReceive(Context context, Intent intent) {
// here I need the time when the alarm should execute.
}
}
Here I like to add, system time is not working for me, because if the device is switch off at the alarm time, it execute that when the device is on after that time. But I need the time when it should execute.
You could create a class that derives from Application which holds all global variables. Then just set a long variable to hold the time before initialising the alarm
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().