I have an app which requires a code to be executed every minute. But the issue is that the code has to be executed at every minute change of the clock. Which means,
If its 12:34 then the code will execute at 12:35 and goes on. But my current code works but it includes the seconds. Meaning,
If its 12:34:30 and the alarm starts, the code is executed. But the code is then executed at 12:35:30.
I want the code to be executed each minute according to the clock of the phone. Below is the current code.
Intent intent2 = new Intent(MainActivity.this, MyABService.class);
PendingIntent pintent = PendingIntent.getService(MainActivity.this, 0, intent2, 0);
AlarmManager alarm_manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm_manager.setRepeating(AlarmManager.RTC, c.getTimeInMillis(), 1 * 1000, pintent);
Im making it execute every second so that the effect takes place at the exact time. Instead of having it every second i need it to repeat itself at every minute change of the clock (every minute)
How do i go about this
Use Intent.ACTION_TIME_TICK This is a broadcast intent fired every minute by the Android OS. Register to it as you would register to a normal system broadcast in code (doesn't work from manifest)
tickReceiver=new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().compareTo(Intent.ACTION_TIME_TICK)==0)
{
//do something
}
};
//Register the broadcast receiver to receive TIME_TICK
registerReceiver(tickReceiver, new IntentFilter(Intent.ACTION_TIME_TICK));
This article describes the complete process.
Use a Calendar to set the time to trigger to the next full minute, and repeat it every minute (60*1000ms)
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.MINUTE, 1);
calendar.set(Calendar.SECOND, 0);
long triggerAt = calendar.getTimeInMillis();
long repeatAfter = 60 * 1000;
alarm_manager.setRepeating(AlarmManager.RTC, triggerAt, repeatAfter, pintent);
Calendar calendar = Calendar.getInstance();
Intent intent = new Intent(context, AnyClass.class);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 60*1000, pendingIntent);
Hope this code solved your problem
Use the Quartz Schedular API, make the corn job which run at every min.
“0 0/1 * * * ?” // Corn expression run at every min
Build the Schedular and trigger like that
SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
Scheduler sched = schedFact.getScheduler();
sched.start();
// define the job and tie it to our HelloJob class
JobDetail job = newJob(HelloJob.class)
.withIdentity("myJob", "group1")
.build();
// Trigger the job to run now, and then every 1 min
Trigger trigger =trigger = newTrigger()
.withIdentity("trigger1", "group1")
.withSchedule(cronSchedule("0 0/1 * * * ?"))
.forJob("myJob", "group1")
.build();
// Tell quartz to schedule the job using our trigger
sched.scheduleJob(job, trigger);
and write your code in HelloJob class
public class HelloJob implements Job {
public void execute(JobExecutionContext context)
throws JobExecutionException;
// Here you write your code which exceute on every min
}
You can use Intent.ACTION_TIME_TICK.
Broadcast Action: The current time has changed. Sent every minute. You cannot receive this through components declared in manifests, only by explicitly registering for it with Context.registerReceiver().
Source:https://developer.android.com/reference/android/content/Intent.html#ACTION_TIME_TICK
IntentFilter tickIntent = new IntentFilter(Intent.ACTION_TIME_TICK);
private BroadcastReceiver receiver = new BroadcastReceiver(){
#Override
public void onReceive(Context c, Intent i) {
// perform per minute task
}
};
registerReceiver(receiver, tickIntent);
You can use below code for your requirement,
Calendar initialCalendar = Calendar.getInstance();
initialCalendar.setTimeInMillis(System.currentTimeMillis());
initialCalendar.set(Calendar.SECOND, 0);
long triggerAtMillis = initialCalendar.getTimeInMillis();
long intervalMillis = 60 * 1000;
alarm_manager.setRepeating(AlarmManager.RTC, triggerAtMillis, intervalMillis, pintent);
Related
I am building an alarm application in Android Java using the C# Xamarin framework. I have done almost everything according to the Android Java play book, but the Alarm Manager Service does not fire my alarm for some reason.
I have a TimePicker and DatePicker objects in my application, I use the TimePicker to read the time and minute set by the user and the the DatePicker to read the day of the week the user intends to be reminded of a certain event. When I do a check on a sample time, I have set as the trigger time, then everything seems to be okay, but there is this parameter of AlarmManager.Set(..,PendingIntent pIntent). I believe the object specifies the operation that needs to be performed when the Alarm has matured. Could that have something to do with why the application does not do anything when the time has matured?
I have declared all the required permissions in my manifest file as follows.
<uses-permission android:name="android.permission.SET_ALARM"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
I then access a calendar instance and ask use my timepicker and datepicker objects to set it. I did this, because I was going to need the calendar time in milliseconds as a parameter in the AlarmManager.Set() call.
//adjust the time in the the calendar variable using the minute and hour from the timepicker
Calendar calendar= Calendar.Instance;
//make sure the instance fields are manipulated hierarchically
calendar.Set(mycalendar.Year,mycalendar.Month,mycalendar.DayOfMonth,timepicker.Hour,timepicker.Minute);
//use the alarm manager to set a new alarm with a pending Intent object
_alarmManager.Set(AlarmType.ElapsedRealtimeWakeup,calendar.TimeInMillis,alarmoperation);
//this pending intent specifies the kind of operation that will happen when
//the alarm goes live
This is the PendingIntent that gets called when the alarm matures
PendingIntent alarmoperation = CreatePendingResult(908, new Intent(), PendingIntentFlags.OneShot);
How do I program a pending intent to fire an alarm if that is what is causing the application not to fire? Is it because I used an empty intent as a constructor parameter when I created the pending intent?
I might be sure that this works:)
Open a Util class, i called it Scheduler, it can schedule notification task or a alarm task :)You choose alarm, since my app needs both :D
/**
* Set the context to use in AlarmManager/Database. They all require {#linkplain Context}
* for many different purposes
* <p>
* For this very reason, Scheduler requires you to provide context. Also, Util class {#link
* com.functionality.app.homepage.LifeStyleUtils} has most of its functions requiring {#link
* Context}.
* </p>
* #param ctx The context to use in issue raising in LifeStyleUitls, e.t.c.
*/
public Scheduler(Context ctx) {
this.ctx = ctx;
}
public int scheduleNotification(LocalDateTime time, Intent intent, int code) {
try {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
cal.set(Calendar.MINUTE, time.getMinute());
cal.set(Calendar.HOUR, time.getHour());
cal.set(Calendar.MONTH, time.getMonthValue());
cal.set(Calendar.YEAR, time.getYear());
cal.set(Calendar.DAY_OF_MONTH, time.getDayOfMonth());
PendingIntent pendingIntent = PendingIntent.getBroadcast(ctx,
code, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmService = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
alarmService.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 1000* 60 * 5,
pendingIntent);
return SUCCESS;
} catch(Exception e) {
return FAILURE;
}
}
/**
* Schedule a task outside the life cycle of app.
*
* #param time The time to set the task.
* #param intent The intent to use, including the Receiver class.
* #return failure or sucess.
*/
public int scheduleTask(LocalDateTime time, Intent intent, int code) {
try {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
cal.set(Calendar.MINUTE, time.getMinute());
cal.set(Calendar.HOUR, time.getHour());
cal.set(Calendar.MONTH, time.getMonthValue());
cal.set(Calendar.YEAR, time.getYear());
cal.set(Calendar.DAY_OF_MONTH, time.getDayOfMonth());
PendingIntent pendingIntent = PendingIntent.getBroadcast(ctx,
code, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmService = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
alarmService.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 1000* 60 * 5,
pendingIntent);
return SUCCESS;
} catch(Exception e) {
return FAILURE;
}
}
public static PendingIntent getPendingIntent(Intent intent, Context context) {
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT
| PendingIntent.FLAG_IMMUTABLE);
}
public void cancelAlarm(PendingIntent pendingIntent) {
AlarmManager alarmManager= (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
}
public void cancelNotification(PendingIntent pendingIntent) {
AlarmManager alarmManager= (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
}
}
Note: use the function "scheduleTask" not "scheduleNotification". Also, If you need reciever code, just comment, i'll send you, i dont wanna send since it will expose my idea, not sending notification since you need alarm. Also, R.raw file is my mp3 samusng galaxy on horizon recording, cant send you that.
I'm currently working on a notification that has to show at a specific time chosen by the user.
BUT when I run it, notifications show but not at the selected time, only when I ask the time in a timepickerdialog appear, before even choosing a time.
Does anyone know how to change the code so that notifications only appear at the time selected?
showDialog(DIALOG_ID); //this is the dialog that asks for an hour and minute.
alarmMethod1();
private void alarmMethod1(){
Calendar calendari1 = Calendar.getInstance();
calendari1.set(Calendar.HOUR_OF_DAY, hour_x);
calendari1.set(Calendar.MINUTE, minute_x);
calendari1.set(Calendar.SECOND, 00);
Intent myIntent1 = new Intent(Main2Activity.this, NotifyService1.class);
AlarmManager alarmManager1 = (AlarmManager) getSystemService(ALARM_SERVICE);
pendingIntent1 = PendingIntent.getService(Main2Activity.this, 0, myIntent1, 0);
alarmManager1.setRepeating(AlarmManager.RTC_WAKEUP, calendari1.getTimeInMillis(), 24 * 60 * 60 * 1000, pendingIntent1);
}
Then here is the class where the intent goes:
public class NotifyService1 extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onCreate(){
Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationManager nNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
Intent intent1 = new Intent(this.getApplicationContext(),Main3Activity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent1, 0);
Notification mNotify = new Notification.Builder(this)
.setContentTitle("Hora d'entrenar!")
.setContentText("Clica per començar entrenament de pit i braços")
.setSmallIcon(R.drawable.logofinal)
.setContentIntent(pIntent)
.setSound(sound)
.build();
nNM.notify(1,mNotify);
}
}
Since Android API 19, all alarms are inexact in order to reduce battery consumption, that means that your alarms will not be triggered exactly when you want, but if you really need to do it, you need to use setExact and then write the repeat alarm handler by yourself, there's no longer a "set exact and repeat". Please, see:
http://developer.android.com/reference/android/app/AlarmManager.html#setRepeating(int, long, long, android.app.PendingIntent)
http://developer.android.com/reference/android/app/AlarmManager.html#setExact(int, long, android.app.PendingIntent)
I'm trying out alarms and have hit a wall. I don't think my alarm is setting up properly because I never get a confirmation after the alarm is supposed to go off. Here's how I call on the alarm manager:
long alarmtime=new GregorianCalendar().getTimeInMillis()+10*1000;//run after 10 seconds
Intent i = new Intent(this, AlarmReceiver.class);
PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
AlarmManager alarmman = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmman.cancel(pi); // cancel any existing alarms
alarmman.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
alarmtime, 10 * 1000, pi);//run every 10 seconds
And here's my AlarmReceiver.java:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "TEST", Toast.LENGTH_LONG).show();
}
}
However, the TEST text does not appear, and I can't figure out why.
Since you are using the AlarmManager.ELAPSED_REALTIME_WAKEUP argument, your initial alarm-time should be base on the elapsed real time of the device:
long alarmtime = SystemClock.elapsedRealtime() + 10 * 1000;
alarmman.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmtime, 10 * 1000, pi);
(see this link).
For a BroadcastReceiver it's probably PendingIntent.getBroadcast() instead of PendingIntent.getService(). You are also cancelling the alarm, just update your PendingIntent like this and try not cancelling before:
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
Read the documentation thoroughly for further information.
Make sure that the BroadcastReceiver is being called by doing a System.out.println("TEST"); instead of Toast. If you are able to see that in your logcat, then the problem probably is that you need to run the Toast in UI thread.
I am registering an Alarm manager in the onResume() state in my MainActivity.java (which is the main activity where the program start)
protected void onResume() {
super.onResume();
if (Helper.isNetworkAvailable(this)) {
Intent intent = new Intent(this, NewsIntentService.class);
PendingIntent pi = PendingIntent.getService(this, 0, intent, 0);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC, System.currentTimeMillis(),
10 * 60 * 1000, pi);
} else {
// nothing done
}
}
However I was getting inconsistent results, the following code runs good and with no errors, it shows that the PendingIntent should be fired at every 10 minutes but the results where on the following from logcat for example:
It starts working good:
2:00 pm (fired), 2:10 pm (fired), 2:30 pm (fired), ...
But after some time:
3:20 pm (fired), 3:27 pm (fired), 3:33 pm (fired), 3:38 pm (fired) ...
The question is at what life cycle of the activity it is best to register an AlarmManager and if what I did is correct what is the reason for the inconsistent run.
use the following code it worked for me:
1- private SharedPreferences prefs;
2-
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Launch SharedPreferences
prefs = getSharedPreferences("Alarm", MODE_PRIVATE);
3-
protected void onResume() {
super.onResume();
if(!prefs.getBoolean(Helper.ALARM_SET, false)) {
Intent intent = new Intent(this, NewsIntentService.class);
PendingIntent pi = PendingIntent.getService(this, 0, intent, 0);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC, System.currentTimeMillis(),
10 * 60 * 1000, pi);
Log.i(Helper.ALARM_SET, "Alarm is set.");
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(Helper.ALARM_SET, true);
editor.commit();
}
}
Explanation:
The Use SharedPreferences to save a boolean value AlARM_SET, simple precise and this code will work even if the phone has restarted or turned off.
Your onResume is getting called at those times, hence triggering the alarm and once again setting it for next ten minutes.
If your end result is to invoke a functionality on Alarm, try to set the next alarm there, call your alarm once in onCreate of your MainActivity.(Check for the first run, use a File for the same or just Shared Preference) Let the rest be handled by the service/function/code which is run upon triggering the alarm.
Check here for complete implementation.
The flow would be something like:
MainActivity--> onCreate--> Check if first run--> Yes--> Register Alarm and execute immediately--> Invoke function/code-->Let this code set the next alarm.
The docs for AlarmManager clearly state that repeating alarms are inexact -- hence the drift you observe via Logcat.
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 targetSdkVersion is earlier than API 19 will continue to have all of their alarms, including repeating alarms, treated as exact.
A block of the code that you can use:
public void schedule(final Context context) {
int alarmCode = YOUR_ALARM_CODE;
final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, alarmCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
final Calendar calendar = yourCalendar();
final AlarmManager alarm = (AlarmManager) context.getSystemService(Activity.ALARM_SERVICE);
final long time = calendar.getTimeInMillis();
alarm.set(AlarmManager.RTC_WAKEUP, time, pendingIntent);
}
I'm currently developing an application which makes use of Android's AlarmManager. I'm trying to add a new alarm to the AlarmManager, but after several hours of trying various things and checking various threads on SO, I'm still at a brick wall. Are there any problems with my code?
Main Activity - saveAlarm() function
/**
* Saves the current alarm. Adds to the database if it doesn't already exist, or updates if it does.
* Also sets alert with AlarmManager.
*/
public void saveAlarm() {
// Create Database instance
DbHandler db = new DbHandler(getApplicationContext());
if(alarm.getId() == -1) {
// Saving a new alarm
db.open();
alarm.setId(db.addAlarm(alarm));
db.close();
}
else {
db.open();
db.updateAlarm(alarm);
db.close();
}
// Create the wakeup intent
Intent intent = new Intent(this, AlarmReceiver.class);
intent.putExtra("alarm_id", alarm.getId());
// Create the Pending Intent
PendingIntent sender = PendingIntent.getBroadcast(this, AlarmPlayer.REQUEST_ALARM + alarm.getId(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Debug
Calendar now = Calendar.getInstance();
long dTime = alarm.getNextAlarmTime().getTimeInMillis() - now.getTimeInMillis();
Log.d(TAG, "Setting alarm for " + (dTime / 1000) + " seconds time");
// Add to Android Alarm Manager
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, alarm.getNextAlarmTime().getTimeInMillis(), sender);
}
I've verified that the correct time is being passed into am.set (see the debug section above it).
AlarmReceiver.class
/**
* This class listens out for broadcasts from AlarmManager
* and launches the AlarmPlayer activity accordingly.
* #author Michael
*
*/
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context c, Intent intent) {
Log.d("RSS Alarm", "Waking up alarm");
// Launch the AlarmPlayer activity
Intent i = new Intent(c, AlarmPlayer.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
c.startActivity(i);
}
}
I also have <receiver android:process=":remote" android:name="AlarmReceiver" /> set up in AndroidManifest.xml. I have no idea what's causing this problem, but it's happening nonetheless. Any help would be greatly appreciated, many thanks in advance.
Edit 1
Changing the timezone to UTC doesn't seem to solve anything, my calendar seems to default to UTC regardless. Current code:
// Debug
Calendar now = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
long dTime = alarm.getNextAlarmTime().getTimeInMillis() - now.getTimeInMillis();
Log.d(TAG, "Setting alarm for " + (dTime / 1000) + " seconds time");
// Add to Android Alarm Manager
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Log.d(TAG, "Timezone offset is " + TimeZone.getDefault().getRawOffset());
Log.d(TAG, "UTC time is currently " + Calendar.getInstance(TimeZone.getTimeZone("UTC")).getTimeInMillis() / 1000);
am.set(AlarmManager.RTC_WAKEUP, (alarm.getNextAlarmTime().getTimeInMillis() - TimeZone.getDefault().getRawOffset()), sender);
Is this possibly a case that AlarmManager.set(AlarmManager.RTC_WAKEUP, ...) needs the time in UTC? This causes problems if you're setting a 'local time' and don't adjust to UTC. In short, the alarm may be being properly added but it doesn't trigger when you expect it unless your time-zone is UTC.
From the docs...
public static final int RTC_WAKEUP Since: API Level 1
Alarm time in System.currentTimeMillis() (wall clock time in UTC), which will wake up the device when it goes off.
In your manifest, I believe you need android:name".AlarmReceiver" note the dot.
If that doesn't do it, post your manifest file. Also, does your logcat mention adding alarm and alarm triggering?
Edit: You might try this
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Other than that, I don't see anything jumping out at me. Good Luck