I want to make my application set alarms every day at lets say 7 am a list of pills for the user. So far I have been doing it when a user adds a new pill, I will set the alarm directly, but I want to make it set alarms for today only. I am able to get a list of pills for some day using xpath, and getting the pills in a list. Now I was thinking if this is feasible to have some kind of hidden activity that keeps running or something that will set the daily pills. If someone could give me directions as to what I should be looking for to solve this problem, any kind of help would be appreciated.
You should use: Alarm Manager. And place it in Service. Read also about BroadcastReceiver
I will give an idea for this.
Schedule the first Alarm at 7 am using the set method of AlarmManager and register a BroadcastReceiver to be executed at 7 am using the same AlarmManager.
At 7 am your Alarm and BroadcastReceiver will execute. In the onReceive method of your BroadcastReceiver again set the Alarm and BroadcastReceiver so that it becomes a self loop.
pseudo code to set broadcastReceiver class:
Intent intent = new Intent(this, broadcastReceiver.class);
intent.putExtra("subject", subject);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,
0, intent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager am= (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, "Your specific time", pendingIntent);
broadcastReceiver.class:
public class TimeAlarm extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//set the alarm and broadcast receiver again
}
Related
Ive been searching for how to using multiple alarms, and did find post in Stackoverflow, but never a straightful answer.
Im trying to set multiple alarms who will call a receiver class (AlarmBcast in my case) and, according to which alarm triggered the call, take different actions.
At this point I followed my way creating diferent receicer classes for each alarm call (and thus a different Intent, each with his own PendintIntent).
I read someone in other thread suggested making a stack (list) of alarms visible, and so using one receiver class for all alarms, but that is not an approach I would like to take.
There is a way to "see" which pendingintent was responsible for the call?.
only the intent is passed, but as there is only one, cant get which call was from it.
Before taking the way of the multiple receivers, this is how my code(pseudo) looked
Setting the alarms...
public class SelectedService extends Service {
//get dates from main
//do some date math
AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
Intent _myIntent = new Intent(this, AlarmBcast.class);
//setting Alarm A
PendingIntent _myPendingIntent = PendingIntent.getBroadcast(this, 123, _myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, partidocalendar.getTimeInMillis(),_myPendingIntent);
//setting Alarm B
PendingIntent _myPendingIntent2 = PendingIntent.getBroadcast(this, 124, _myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, convopartidocalendar.getTimeInMillis(),_myPendingIntent2);
//setting Alarm C
The receiver as i wa planning it ...
public class AlarmBcast extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//how to identify call A from B ??
if(AlarmA){}
if(AlarmB){}
}
Maybe i have some conceptual mistake? Back to programming since after 15 years (mostly assembler before)
You can put an "extra" in the Intent that identifies which alarm it is. For example:
_myIntent.putExtra("alarm", "A");
Do this before calling PendingIntent.getBroadcast() for each different alarm.
Then, in your BroadcastReceiver.onReceive() you can check the "extra" in the Intent to determine which alarm got triggered.
I fixed this issue by separating and creating two different Notification Channel and Classes
I'm developing an app which you can schedule your time and It reminds you on time just like google calendar. I use AlarmManager class and set a Repeating task to check Database every one minute and see if there is any alarm on that time or not.
#Override
public void onReceive(Context context, Intent intent) {
Calendar now = Calendar.getInstance();
doRepeatingWorks(now.getTimeInMillis()); // Like Checking if one day passed to do some tasks
checkDbIfThereIsSomeSchedule(now);
}
And I call this to start alarm manager:
public void setAlarm(Context context) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), G.ALARM_CHECK_INTERVAL_MILIS, pendingIntent);
}
But it's inaccurate and sometimes I figure out that the task killer apps kill my alarm and make it totally worthless.
Although using a foregroundService is battery consuming and it goes on user's nerve with the notification.
Is there any solutions or alternatives for this problem?
I use AlarmManager class and set a Repeating task to check Database every one minute and see if there is any alarm on that time or not
That is a truly awful approach. This sort of behavior is precisely why Doze mode and app standby were added in Android 6.0.
Is there any solutions or alternatives for this problem?"
Schedule an alarm event for first event. When you get control, notify the user about the event, then schedule an alarm event for the next event in sequence. If the user adds a new event that is sooner than your first event, cancel the previous alarm and schedule one for the new first event.
You don't need to check there is an alarm in each 1 min. I hope this post helps you - Scheduled Alarm Manager not working Android
I am trying to figure this out for a while now.
In my activity I have set an alarm manager to trigger every 2 mins(for testing) and invoke a service via a receiver. The service is suppose to make network calls etc.
My problem is the AlarmManager triggers the first time correctly but never triggers it again. What did I miss?
In my activity I do this -
//Register an alarm manager
//If no alarm is set
Intent alarmIntent = new Intent(context, AlarmReceiver.class);
alarmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);
if(!defaultSharedPref.getBoolean("isAlarmSet",false)){
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
manager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(),
R.string.interval,
pendingIntent);
editor = defaultSharedPref.edit();
editor.putBoolean("isAlarmSet",true);
editor.commit();
}
In my manifest:-
<receiver android:process=":remote" android:name=".receiver.AlarmReceiver" />
<service android:name=".service.AlarmService"/>
My receiver :-
public class AlarmReceiver extends WakefulBroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, AlarmService.class);
startWakefulService(context,i);
}
}
I even tried the "setRepeating" but no luck. It still triggers only once.
Can someone point out where I missed something?
Thanks in advance.
As the interval for your repeating timer you are giving a resource id - R.string.interval. This doesn't make sense, but will compile since it's an integer. If you want your interval as a resource, you'd be better of using an integer resource, but the most crucial change you need is to pass the actual value of the resource rather than the resource id. So for this, use Resources.getInteger or getString.
This should work, however I encourage you not to use a string resource at all:
manager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(),
Integer.parseInt(getResources().getString(R.string.interval)),
pendingIntent);`
The reason you aren't seeing any triggered alarms in practice is that resource ids are very large integers, typically in the 0x8000000 range, so you're effectively setting a recurrent alarm with a very very long interval. If you wait for a month or so, the alarm would be triggered. :-)
If you want a more flexible way to schedule jobs, I would recommend this library that abstracts for you the used scheduler: https://github.com/evernote/android-job
I have a situation in my application. I am calling a service using an alarm. The alarm wakes up every 5 min and calls the service.
But it may so happen that the user might close my app and I am allowing the functionality of the service to work even if the user is not using my app.
To stop the service there are two ways either the user comes back to the app and presses a button which will cancel the alarm OR the second way is say after x time I want to stop the service i.e cancel the alarm from a broadcast receiver.
Now how can I do the second way ? When I tried to get reference of the AlarmManager it is giving me error of Null Pointer. (I am accessing this alarm manager from a broadcast receiver)
Can anyone give me suggestion on how to cancel repeating alarms from outside the activity context ?
Thanks :)
You can stop your service like this
context.stopService(new Intent(context, YourService.class))
Also in order to cancel the alarm you can do this
Intent intent = new Intent(this, YourClass.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 1253, intent, PendingIntent.FLAG_UPDATE_CURRENT| Intent.FILL_IN_DATA);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
I hope this might help you
In your BroadcastReceiver try this:
public void onReceive(Context context, Intent intent) {
context.stopService(new Intent(context, YourService.class));
}
I have a big problem with my app for several days now. I appologize if my english is not so native in advance. I implemented an AlarmManager to give the user of my app the option to start a certain service at any time of the current or the next day. So e.g. the user might choose to set the time for my service to tomorrow at 08:00 a.m. and then starts the service.
The alarm manager should now wait the calculated time from now till the chosen time (i calculated the time also manually and it is correct!) and then start the service. My problem now is that sometimes the alarmmanager is starting my service and somtimes not. It seems that if it has to wait for lets say more than 4 hours it is not working any more and my service is not called. I have set all neccessary permission otherwise it would not work at all. You can have a look at the code of the alarmmanager below:
someIntent = new Intent();
someIntent.setAction("START_SERVICE");
AlarmManager alarams ;
alarmIntent = PendingIntent.getBroadcast(MainActivity.this, 0, someIntent, PendingIntent.FLAG_CANCEL_CURRENT);
alarams = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarams.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+delay, alarmIntent);
The broadcast receiver is implemented like this (and it is registered!):
alarmReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Intent myIntent = new Intent(MainActivity.this, MyService.class);
startService(myIntent);
}
};
As I told you, if it is not working it stops before starting the service.
EDIT:
I have an idea. I read something in this thread: Android long running service with alarm manager and inner broadcast receiver
It might be, that my constructor for the intent "someIntent" only works for BroadcastReceivers declared in the manifest file. So in my case I should maybe use someIntent = new Intent("START_SERVICE") instead of someIntent = new Intent(); someIntent.setAction("START_SERVICE"). This effect is called tunneling - i will figure it out, if it works i will post my experience here. Thanks for the well explained answer on the mentioned thread! If you have any other ideas or the same experiences like me please let me know!
eMu
If the device is shutdown and start up then you will not get the alarm maanger broadcast receiver.
Implement OnBootReceiver which will receive the OnBoot completed and there you can start your pending alarms that were not fired.