I have a service, which I want to run each day so check some stuff in my db, and if needed create a notification.
To run my service each day, I used an alarmManager, which works fine for the first time, but as soon as in starts my services gets in an infinite loop, I know this is because of the alarmManager since it just gets in the loop when the alarmmanager is starting. here is the code of my service:
public class MyService extends Service {
...
public MyService() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
checkMechanicUseer();
this.stopSelf();
return START_NOT_STICKY;
}
private void checkMechanicUseer() {
...
}
#Override
public void onDestroy() {
super.onDestroy();
final SharedPreferences settings = getSharedPreferences("MYSETTINGS",0);
int time = settings.getInt("time",9);
Calendar calNow = Calendar.getInstance();
Calendar calSet = (Calendar) calNow.clone();
calSet.set(Calendar.HOUR_OF_DAY, 9);
calSet.set(Calendar.MINUTE, 0);
calSet.set(Calendar.SECOND, 0);
calSet.set(Calendar.MILLISECOND, 0); // I want it to trigger at 09:00 am each day
AlarmManager alarm = (AlarmManager)getSystemService(ALARM_SERVICE);
alarm.setRepeating(
alarm.RTC_WAKEUP,
calSet.getTimeInMillis() ,(1000 * 60 ),
PendingIntent.getService(this, 0, new Intent(this, MyService.class), 0)
); // I set the (1000 * 60 ) so I can check it with 1 min interval, so I wont need to wait one day for it ... of course I need to change it to (1000 * 60 * 60 * 24)
Toast.makeText(MyService.this, "Service destroyed",Toast.LENGTH_SHORT).show();
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
I guess I need to cancel my alarm some where, and then set another one. but have no idea how or where to do it
Still have the problem if I change the alarm.setRepeat with alarm.set as follow:
alarm.set(
alarm.RTC_WAKEUP,
calSet.getTimeInMillis() + (1000 * 60 ),
PendingIntent.getService(this, 0, new Intent(this, MyService.class), 0)
);
I think that it is because you set the alarm for a past date, first fire at 9 o'clock then you reset the alarm for 9 o'clock but this time is in the past so the alarm is fire immediatly and you have a nice loop.
Check if the time is not in the past, if it is, add a day to your calendar.
Related
I want to create reminder app
I have searched a lot of places but couldnt find a clean sequential explanation of how to start a service (or if thats not possible then an activity) at a specific time daily using the AlarmManager?
i want start service at specific date and time and for example Six months after that date start the service again And continue this cycle
Calendar cur_cal = new GregorianCalendar();
cur_cal.setTimeInMillis(System.currentTimeMillis());//set the current time and date for this calendar
Calendar cal = new GregorianCalendar();
cal.add(Calendar.YEAR, 2018);
cal.set(Calendar.MONTH, 2);
cal.set(Calendar.DAY_OF_MONTH, 12);
cal.set(Calendar.HOUR_OF_DAY, 9);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
Intent intent = new Intent(ProfileList.this, BroadcastedReceiver.class);
PendingIntent pintent = PendingIntent.getService(ProfileList.this, 0, intent, 0);
AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 1000, pintent);
i tried this code to activate the alarm at 2018-02/12 9:00... this is Works on this date but i have problem to repeating after for example six month...How do I change the codes to be start service every six months?
NOTE: Dates are stored in the database And they will be called from there
public class AddService extends Service
{
InterstitialAd mInterstitialAd;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//Your Logic
stopSelf();
return START_NOT_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.set(alarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000*60*60),
PendingIntent.getService(this,0,new Intent(this,AddService.class),0));
}
}
// Here your service will call every 1 hour, you can change time according to that
it's better to use job scheduler or firebase dispatcher for your requirement
refer this links
https://medium.com/google-developers/scheduling-jobs-like-a-pro-with-jobscheduler-286ef8510129
https://github.com/firebase/firebase-jobdispatcher-android
I am trying to play a ringtone at exactly at 7 PM everyday but it is playing ringtone immediately after its pending intent is registering broadcast.
I called the service in the foreground on a button click and created pending intent there in onStartCommand:
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
startForeground(FOREGROUND_ID,
buildForegroundNotification("DummyApp"));
c = Calendar.getInstance();
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
int interval = 1000 * 60 * 60*24;
c.setTimeInMillis(System.currentTimeMillis());
c.set(Calendar.HOUR, 19);
c.set(Calendar.MINUTE,00);
manager.setRepeating(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(),
interval, pendingIntent);
Intent alarmIntent = new Intent(AlarmService.this, DataProcessor.class);
pendingIntent = PendingIntent.getBroadcast(AlarmService.this, 0,
alarmIntent, 0);
return START_STICKY;
}
Now I am playing a ringtone on receiving this broadcast in DataProcessor class the on Receive method of Data Processor class:
#Override
public void onReceive(Context ctx,Intent intent) {
playRIng(ctx);
}
But when I run this code,click the button,service is created but alarm is fired immediately after the AlarmService is called and ringtone is played also.How it is possible because I am giving the exact 7 O clock time when registering broadcast.?
Googled a lot but found the same code only and nothing else.Every code is able to play the ringtone on the time but it also plays the ringtone immediately after the broadcast is registered.
Why you don't use a condition?:
#Override
public void onReceive(Context ctx,Intent intent) {
Calendar c = Calendar.getInstance();
int hour = c.get(Calendar.HOUR);
if(hour==19)
{
playRIng(ctx);
}
}
If you ran that code at 9pm you would be telling the AlarmManager that the intent should have been run for the first time 2 hours ago.
You need to check if the Calendar time is behind the current time.
If it is you need to add a day to the calendar so that it first triggers tomorrow at 7pm.
Something like this might work:
c = Calendar.getInstance();
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
int interval = 1000 * 60 * 60 * 24;
// Not needed
// c.setTimeInMillis(System.currentTimeMillis());
c.set(Calendar.HOUR, 19);
c.set(Calendar.MINUTE, 00);
// ** Add this **
// Check if the Calendar 7pm is in the past
if (c.getTimeInMillis() < System.currentTimeMillis())
c.add(Calendar.DAY_OF_YEAR, 1); // It is so tell it to run tomorrow instead
manager.setRepeating(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), interval, pendingIntent);
Intent alarmIntent = new Intent(AlarmService.this, DataProcessor.class);
pendingIntent = PendingIntent.getBroadcast(AlarmService.this, 0, alarmIntent, 0);
You can try the example at developers website understanding the samplecode available there.May be there is some programming mistake in your code but the sample code available there is working exactly you want.
Scheduling Repeating Alarms
Best way, Play with hour & mintue.
Note: Please check your time formate. In my case it's 24 hr formate
Example:
Calendar c = Calendar.getInstance();
//for 12 hr formate user int hour = c.get(Calendar.HOUR);
int hour = c.get(Calendar.HOUR_OF_DAY);
int minute = c.get(Calendar.MINUTE);
//Log.e("time",""+hour+":"+minute);
if (hour == 10 && minute == 0 ) {
}
I know this is most common thread in SO but i didn't find any answer for my question . I want to trigger dynamic broadcast receiver at particular time. For this i am using below code
public void method1() {
br = new BroadcastReceiver() {
#Override
public void onReceive(Context c, Intent i) {
doTASK();
}
};
registerReceiver(br, new IntentFilter("com.XXXX.wakeup"));
pi = PendingIntent.getBroadcast(this, 0,
new Intent("com.xxxx.wakeup"), 0);
am = (AlarmManager) (this.getSystemService(Context.ALARM_SERVICE));
setAlarmManagerObject();
}
And setAlarmManagerObject() method is here
public void setAlarmManagerObject() {
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH);
int day = cal.get(Calendar.DAY_OF_MONTH);
cal.set(year, month, day
, com.XXXX.Constants.AlarmHour
, com.xxxx.Constants.AlarmMinute
, com.xxxx.AlarmSecond);
am.setRepeating(AlarmManager.ELAPSED_REALTIME, cal.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pi);
}
My problem is that when i used AlarmManager.RTC_WAKEUP it wake up when device is off. I don't want this property in my app. So i used AlarmManager.ELAPSED_REALTIME, but with ELAPSED_REALTIME alarm manager is not triggering. I want that my alarm manager trigger exact at same time. If device is off or sleep condition then alarm manager will also off after device wake up.It should trigger at exact time. Any help will really appreciated.
You need to use something like this:-
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP (or AlarmManager.ELAPSED_REALTIME),
SystemClock.elapsedRealtime() + Constants.DELAY_IN_MILLIS,
pendingIntent);
You can calculate DELAY_IN_MILLIS which is time delay in milliseconds from current system time.
For repeating alarm you can have code something like this:-
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + Constants.DELAY_IN_MILLIS,
Constants.ONE_DAY_IN_MILLIS,
pendingIntent);
I have started alarm of 9:00 AM in android on Boot Completed. But fires alarm every minute after it has completed boot.
My Requirement is it should set Alarm after boot but only fires alarm at 9:00 AM.
Here is my code:
public class AlarmUtil {
private PendingIntent alarmIntent;
public static void setAlarm(Context context) {
AlarmManager alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 9);
calendar.set(Calendar.MINUTE, 00);
calendar.set(Calendar.SECOND, 00);
calendar.set(Calendar.AM_PM, Calendar.AM);
//calendar.setTimeInMillis(calendar.getTimeInMillis());
calendar.add(Calendar.SECOND, 1);
Intent intent = new Intent(context, Services.class);
PendingIntent pintent = PendingIntent.getService(context, 123456789,
intent, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), 1 * 60 * 1000, pintent);
}
}
public class AlarmBroadcastReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
Toast.makeText(context, "Booted!", Toast.LENGTH_SHORT).show();
AlarmUtil.setAlarm(context);
}
}
}
services (My service Class)
public class Services extends IntentService {
public Services(String name) {
super("services");
// TODO Auto-generated constructor stub
}
public Services() {
super("services");
// TODO Auto-generated constructor stub
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
MyApp.counter += 1;
Toast.makeText(getApplicationContext(),
"Service started: " + MyApp.counter, Toast.LENGTH_LONG).show();
return START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
protected void onHandleIntent(Intent intent) {
Toast.makeText(getApplicationContext(), "handling intent",
Toast.LENGTH_LONG).show();
}
}
where i am lacking. Please help me. Thanks in advance.
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), 1 * 60 * 1000, pintent);
By calling setRepeating(), you are instructing it to fire the intent on every minute. You probably meant to use set() or setExact() instead.
Additionally, you're setting the alarm for 9:00 on the current date. I'm not exactly sure what your objective is but if you want an alarm for the "next 9:00" (i.e. as an alarm clock) you should probably add a day if the current time is greater than 9:00. From the documentation:
If the stated trigger time is in the past, the alarm will be triggered
immediately.
EDIT: If what you need is to fire this alarm every day at 9:00, then setRepeating() is correct, but the time in milliseconds should be AlarmManager.INTERVAL_DAY. Be mindful of the note about past alarms, though. If you boot your phone, say, at 10:00 AM, and you use your current code, you will get an immediate alarm in addition to the future ones.
And, as #DerGolem pointed out, if you target API level 19 then these alarms will be inexact (and there is no setRepeatingExact()). If you need exact alarms, then you will have to schedule one with setExact(), then the next one when that one fires, and so on.
Hi I have used following code and able to generate alarm at 9 Am each day
alarmMgr = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmService.class);
PendingIntent pintent = PendingIntent.getService(this, 123456789,
intent, 0);
// Set the alarm to start at 8:30 a.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 9);
calendar.set(Calendar.MINUTE, 00);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), 1000 * 60 * 1 * 60 * 24, pintent);
you need to replace "1 * 60 * 1000" with AlarmManager.INTERVAL_DAY to set it daily
Hi I am currently working with AlarmManager. I have written a code given below. As per code the AlarmManager should be triggered after 10 Sec, but here in my code the alarm manager triggers immediately. Please help.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
int alarmType = AlarmManager.ELAPSED_REALTIME_WAKEUP;
long timeOrLengthofWait = 10000;
Intent intentToFire = new Intent(this, AlarmReciever.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 0, intentToFire, 0);
alarmManager.set(alarmType, timeOrLengthofWait, alarmIntent);
}
}
And My AlarmReciever Class
public class AlarmReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String phoneNumberReciever="5556";
String message="Alarm Triggered";
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumberReciever, null, message, null, null);
Toast.makeText(context," A message has been sent", Toast.LENGTH_LONG).show();
Log.d("Alarm ", "Alarm Has been triggered and sms send");
}
}
I have Already added required permissions in manifest.
You are using an alarm type of ELAPSED_REALTIME_WAKEUP. That means that the second parameter to set() must be the number of milliseconds from now, where now is expressed as SystemClock.elapsedRealtime().
If your goal is to have this occur 10000 milliseconds from the time you make the set() call, that set() call should be:
alarmManager.set(alarmType, SystemClock.elapsedRealtime()+timeOrLengthofWait, alarmIntent);
If you are creating PendingIntent of an alarm for past time it will be fired immediately. Example - Schedule alarm for today 8AM but executing code around 11AM will fire immediately.
Solution:
cal.add(Calendar.DATE, 1);
long delay = 24 * 60 * 60 * 1000;
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), delay,pendingIntent);`
This will fire the event on next day at specified time (i.e 8AM);