start a service with Alarmmanager at specific date and time and Repeating - android

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

Related

Alarm is not triggering on the same Date

I want to reboot device on particular time so i am using alarm manager for that.below is the code of my activity.
public class MainActivity extends AppCompatActivity {
private static int timeHour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
private static int timeMinute = Calendar.getInstance().get(Calendar.MINUTE);
AlarmManager alarmManager;
private PendingIntent pendingIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent myIntent = new Intent(MainActivity.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, 0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(Calendar.MINUTE, 02);
alarmManager.cancel(pendingIntent);
// if(Calendar.getInstance().after(calendar)){
// // Move to tomorrow
// calendar.add(Calendar.DATE, 1);
// }
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),AlarmManager.INTERVAL_DAY, pendingIntent);
//
// alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
// SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_DAY,
// AlarmManager.INTERVAL_DAY, pendingIntent);
}
}
and this is my receiver
public class AlarmReceiver extends BroadcastReceiver {
public static void rebootDevice() {
try {
Process process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
os.writeBytes("reboot \n");
} catch (Throwable t) {
t.printStackTrace();
}
}
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Triggered", Toast.LENGTH_SHORT).show();
Log.d("Gajanand", "onReceive: Triggered");
rebootDevice();
}
}
Yes code is working fine but not on the exact date.for example if i run the same code now. alarm not triggers if i change the date it triggers. i am not getting what is the problem with code and there is 10 seconds delay in triggering alarm. any help
There are two problems with your code:
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(Calendar.MINUTE, 02);
Here you're setting HOUR_OF_DAY and MINUTE but the SECOND field still has its initial value, so the alarm won't be triggered exactly on the minute
(unless you called calendar.setTimeInMillis(System.currentTimeMillis()) exactly on the minute, which is quite unlikely).
Should be something like this:
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(Calendar.MINUTE, 2);
calendar.set(Calendar.SECOND, 0); // setting seconds to 0
setRepeating() is inexact and doesn't work with Doze.
For exact trigger times you should use exact alarms, check this answer for an example.
This is from the documentation
Note: as of API 19, all repeating alarms are inexact. If your
application needs precise delivery times then it must use one-time
exact alarms, rescheduling each time as described above. Legacy applications
whose {#code targetSdkVersion} is earlier than API 19 will continue to have all
of their alarms, including repeating alarms, treated as exact.
Repeating alarms are always inexact so that they wont consume much battery. They may be fired a bit later than the expected time. If you want your alarm to exact, don't make it repeating. Set it again once you receive the alarm

Alarm Manager does not works properly

Alarm Manager does not works properly, as sometimes it triggers the alarm at rigth time but sometimes it triggers alarm after a delayed time of 2-5 minutes and some times it even not triggers the alarm
public static void setAlarmTime(Context context, String userName, String selectedRitual,int dayOfWeek, int hourOfDay, int minute, int rStamp, boolean isUpdate)
{
Calendar now = Calendar.getInstance();
Calendar cal = Calendar.getInstance();
cal.set(Calendar.DAY_OF_WEEK, dayOfWeek);
cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
cal.set(Calendar.MINUTE, minute);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
long alarmTime = cal.getTimeInMillis();
Intent intent= new Intent(context, AlarmReceiver.class);
intent.putExtra(AppsConstant.SELECTED_RITUAL, selectedRitual);
intent.putExtra(AppsConstant.user_name, userName);
intent.putExtra("alarmTime", "day"+dayOfWeek+" hour"+hourOfDay+":"+minute);
PendingIntent alarmIntent;
if(!isUpdate)
alarmIntent = PendingIntent.getBroadcast(context.getApplicationContext(), rStamp, intent, 0/*PendingIntent.FLAG_UPDATE_CURRENT*/);
else
alarmIntent = PendingIntent.getBroadcast(context.getApplicationContext(), rStamp, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager=(AlarmManager)context.getSystemService(context.ALARM_SERVICE);
//check whether the time is earlier than current time.
if(cal.before(now))
{
alarmTime = cal.getTimeInMillis()+(alarmManager.INTERVAL_DAY * 7);
}
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, alarmTime, AlarmManager.INTERVAL_DAY * 7, alarmIntent);
}
You're using setInexactRepeating(), which, by documentation, does not always trigger at exactly the time given:
Schedule a repeating alarm that has inexact trigger time requirements;
for example, an alarm that repeats every hour, but not necessarily at
the top of every hour.
If it does not trigger at all when you think it should, consider that you might be rescheduling an existing alarm for the future in some cases.

Alarm is running immediately after it is created

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 ) {
}

Alarm manager Not triggering with correct time

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);

setting alarm on boot time at a specific time every day

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

Categories

Resources