Am creating an application that fetch data from webservice. I have been while(true) and sleeping the loop at a specific milliseconds.. i had like to make the service action(fetching data from webservice) to always start at a specific time.. instead on being on always and pausing by Thread.sleep(milli)... Thanks
this is what have been using
while(true)
{
///pullDataFromWebservice();
Thread.sleep(600000);
}
Use the Alarm API. It is way safer than having a sleep & poll service.
Why?
Because Android is very likely to reclaim such a long running services when resources turn low, resulting
in your delayed logic never being called!
An example for activating a callback in 1 hour from now:
private PendingIntent pIntent;
AlarmManager manager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, MyDelayedReceiver.class); <------- the receiver to be activated
pIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() +
60*60*1000, pIntent); <---------- activation interval
Try using AlarmManager - A bit battery eater though
AlarmManager alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, YourClass.class);
PendingIntent pIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
Calendar cal= Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 19);
cal.set(Calendar.MINUTE, 20);
cal.set(Calendar.SECOND, 0);
alarmMgr.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pIntent);
//RTC_WAKEUP to enable this alarm even in switched off mode.
Related
In my app, I need to start a service at 2:00pm daily. Right now I wrote the code to trigger the alarm once, this code is ran every time I open the app:
AlarmManager alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, DownloadReceiver.class);
PendingIntent pIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmMgr.cancel(pIntent);
Calendar cal= Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
cal.set(Calendar.HOUR_OF_DAY,refreshhour);
cal.set(Calendar.MINUTE,refreshmin);
cal.set(Calendar.SECOND, 0);
// if the scheduler date is passed, move scheduler time to tomorrow
if (System.currentTimeMillis() > cal.getTimeInMillis()) {
cal.add(Calendar.DAY_OF_YEAR, 1);
}
if(android.os.Build.VERSION.SDK_INT>=23) {
alarmMgr.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
cal.getTimeInMillis(), pIntent);
}
else{
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pIntent);
}
Q1. I used setAndAllowWhileIdle() for sdk above 23 in case the device is in Doze mode. I cannot find any option in this function that I can set the alarm to repeat every day.
Q2. I also have questions about setInexactRepeating() , normally it is set to repeat every day by setting the parameter INTERVAL_DAY , but in the docs, it says
As of API 19, all repeating alarms will be inexact and subject to
batching with other alarms regardless of their stated repeat interval.
Does this mean INTERVAL_DAY does not work anymore, so how can I set the alarm daily without rerunning this function and reset alarmManager?
Try below code will solve your problem-
AlarmManager alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
boolean flag = (PendingIntent.getBroadcast(this, 0,
new Intent("totime.action.string"),
PendingIntent.FLAG_NO_CREATE) != null);
if(!flag)
{
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 14);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
Intent intent = new Intent("totime.action.string");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) Data_Graph.this.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),(24*60*60*1000), pendingIntent);
}
Intent myAlarm = new Intent(context, AlarmReceiver.class);
PendingIntent recurringAlarm = PendingIntent.getBroadcast(context.getApplicationContext(), 0, myAlarm, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Calendar updateTime = Calendar.getInstance();
alarms.setRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), AlarmManager.INTERVAL_DAY / 3, recurringAlarm);
Say this piece of code is executed more than once. This results in that many alarms being created (I find this info from dumpsys where it says X# wakes - X# alarms).
I've been told that setting the same request code and same intent cannot start the alarm the second time.
I want to deliver timed notifications (everyday, 5:00AM), and tried to do this using AlarmManager with the following code:
Intent appIntent = new Intent(this, NotificationService.class);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
PendingIntent penIntent = PendingIntent.getService(this, 0,
appIntent, 0);
alarmManager.cancel(penIntent);
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 5);
cal.set(Calendar.MINUTE, 00);
cal.set(Calendar.SECOND, 00);
alarmManager.setRepeating(AlarmManager.RTC, cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, penIntent);
The NotificationService.class looks (at least the important parts) like this:
int id = 001;
NotificationManager mNotifyMng = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
MainActivity.this).setSmallIcon(R.drawable.icon).setContentTitle("Test")
.setContentText("Test!");
mNotifyMng.notify(id, mBuilder.build());
stopSelf();
I can't seem to get it to work. When I set the emulator clock to 4:59 or something and wait for it to change to 5:00, there is no notification showing up and I can't figure another way to test it.
I hope you know some way to test it or find the bug in my code.
I believe the problem is that you cancel the PendingIntent but then you need to recreate it again before setting alarmManager.
//cancel pendingIntent
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
PendingIntent penIntent = PendingIntent.getService(this, 0,appIntent, 0);
alarmManager.cancel(penIntent);
//reset pendingIntent
Intent appIntent = new Intent(this, NotificationService.class);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
PendingIntent penIntent = PendingIntent.getService(this, 0,appIntent, 0);
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 5);
cal.set(Calendar.MINUTE, 00);
cal.set(Calendar.SECOND, 00);
alarmManager.setRepeating(AlarmManager.RTC, cal.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, penIntent);
To cancel a PendingIntent you need to create it exactly as you did the first time then call AlarmManagers cancel() on it as you are. But then you need to create it again to set the alarm on the PendingIntent
**I hope you know some way to test...
There may be a better way but, for testing purposes, I will sometimes set a global debug flag which will change times between testing and production. So say 4 hours might be 2 minutes. Times of the day may be a little more tricky but you can change the time to whatever hour, minute, or whatever is close. Once you know it is triggering at the right time then you can change it back and still test when that time of day comes around but you now know it should be working.
I am using AlarmManager for my Timer. I have 2 classes.
In the first class (MainActivity) I am starting my alarm with the next code:
public void startAlarm(long Seconds) {
Intent myIntent = new Intent(MainActivity.this, MyAlarmService.class);
pendingIntent = PendingIntent.getService(MainActivity.this, 13141337,
myIntent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, (int) Seconds);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
pendingIntent);
}
In another class (AlarmSound), where the alarm goes off and the phone vibrates, I'm calling my cancel Alarm method.
public void stopAlarm(){
Intent intentstop = new Intent(AlarmSound.this, MyAlarmService.class);
PendingIntent senderstop = PendingIntent.getBroadcast(AlarmSound.this,
13141337, intentstop, 0);
AlarmManager myalarm = (AlarmManager) getSystemService(ALARM_SERVICE);
myalarm.cancel(senderstop);
Log.w("Karl","stopAlarm?");
}
Is this the correct way to do this? Because my alarm constantly goes off on android 4.1.
Thanks in advance!
Your Cancel wont work. The pending Intents have to match - since they have a different context (MainActivity and AlarmSound) this cancel wont work. You have to also use getService on both.
You can
a) try to recreate a matching pending Intent
b) get the pendingIntent that started the Service in the Service and use that to cancel
But usually every Alarm just goes off once if you dont use setRepeating().
Are you sure you are terminating your Service correctly with stopself() and are giving it the right flag in the onStartCommand() Method?
I want to set phones alarm in phone.
Can anybody say how to do that?
I got the code from net, and try but the alram not set to phone.
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
Intent activate = new Intent(this, Alaram.class);
AlarmManager alarams ;
PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 0, activate, 0);
alarams = (AlarmManager) getSystemService(ALARM_SERVICE);
alarams.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmIntent);
In this code we are provide intent as Alaram.class.
Then what should be written in this Alram.class so that alarm will set to the mobile.
I think you misunderstood what the AlarmManager is good for. It starts your code on a given Point, it doesn't set the phones ring tone.
If you want to set the Phones Alarm sound, this might be helpful (from the standard Android Music Player):
// Set the system setting to make this the current ringtone
MusicUtils.setRingtone(this, mService.getAudioId());
You are setting alarm time as current time in millisecond it will be exceed when the alarmmanager wake up....So,here i modified your code.check this it will work.That alaram will start after 5 seconds...i mean your Alaram activity will start within 5 seconds.
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
Intent activate = new Intent(this, Alaram.class);
AlarmManager alarams ;
PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 0, activate, 0);
alarams = (AlarmManager) getSystemService(ALARM_SERVICE);
alarams.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis()+5000, alarmIntent);