In my app, I want to kick off an timer that triggers an action every x minutes, regardless if the user is currently in the app or not. I have been reading around and am not sure which combo of Broadcast and Receiver types I should use - any guidance would be helpful.
Example of user actions:
User hits a button, sets initial timer (alarm)
Timer is reached, trigger an action and set the timer again
Repeat until it has run for x minutes
when the user hits button set alarm as
AlarmManager am = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
am.setRepeating (AlarmManager.Type,
long triggeringtime,
long interval,
PendingIntent operation);
here triggeringtime is how to time it shud take to take an action
and interval how to much time it would take to do the same.
here operation is the Intent which you need to execute like it may be an activity or Service you can Define it as
operation = PendingIntent.getActivity( context, 0, intent or service, 0);
2 and 3 step will be continuously run thats what the alarm manager does.
This alarm continues repeating until explicitly removed with
cancel(AlarmManager.OnAlarmListener).
I am a beginner Sry if i wrong. Hope it helps!
Android JobScheduler
You can find a lot of tutorial online.
Related
I try to build a Tamagotchi game with Unity for Android. The Tamagotchi has a food attribute that should go down even when the Game is closed.
So my approach would be build a IntentService that holds the variables, increase and decrease them if needed. For Batterie reasons i would use Alarm manager to start the Service only every 10 minutes if the App is closed. If the app is started it would bind the Service so it never closes and i can get the Variables.
Is there a more efficient way to handle this? I dont want my app to battery drain too much.
€:
If the food gets low it should also display a notification.
There is indeed a more efficient way to handle this.
Why don't you just save a timestamp when the user closes the app and calculate the time passed when the user opens the app again?
Then you can calculate the new food attribute you're done.
Edit: If you want to show notifications if the food is low you need the alarm manager.
Here is some example code:
public static void registerAlarm(Context context) {
Intent i = new Intent(context, YOURBROADCASTRECIEVER.class);
PendingIntent sender = PendingIntent.getBroadcast(context,REQUEST_CODE, i, 0);
// We want the alarm to go off 3 seconds from now.
long startTime = SystemClock.elapsedRealtime();
startTime += 60000;//start 1 minute after first register.
// Schedule the alarm!
AlarmManager am = (AlarmManager) context.getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, startTime, 900000, sender); // 15min interval
}
You can also calculate when the Tamagotchi will be hungry just before the game is closed and set alarm only to that point to show notification.. unless the game opened again so you clear all notifications.
I'm implementing an app on Android. I've just added a new service that is called on boot-completed. This service creates a new thread that is simply a loop, making something minute after minute. To wait the next minute I used Thread.sleep(60000) but it doesn't work: after the waiting period no other action is performed. It seems that the app is closed or waiting permanentely.
Is there another way to make a loop-service avoiding Thread.sleep? I don't think it is a problem of code because if I call the main method of the service on the app starting it works (it is a problem related to the service)
Thank you in advance
I think the problem is related to the "scan media" of my LG L9 II.. when the "scan media" (I think is about my sd card) is completed all my service are killed (or something like it). Any suggestion?
Consider using AlarmManager to invoke your service. Below example illustrates how to establish repeating events every minute from AlarmManager.
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(getBaseContext(), AlarmReceiver.class);
PendingIntent pending = PendingIntent.getBroadcast(getBaseContext(), 0, intent, 0);
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), ONE_MINUTE, pending);
Services don't have their own thread, the share the main (UI) thread. If you want to do something every minute, create a new thread and have it do something once a minute.
There is almost never a good reason to use Thread.sleep(...) or explicitly create threads in Android. If you need something to happen every 60 seconds, create a Handler and use its postDelayed(...) methods. You can post a task that will re-post itself each time it runs. Just make sure you cancel it when your app is shutting down.
In order to implement a reminder, I need to set a memo like: "starting from today, show a memo, each friday, one week yes and one no"
So, I think I can determin for each memo, what is the next date I have to show it. And then pass this date to a Timer like this:
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
//show my memo
});
}}, date); //
Supposing now is Mon 26/11/2012 how can I determine when occurs the first friday (according to the aforementioned memo?
I'm not sure this mechanism is enough good, if someone can suggest me another approch I would be grateful.
Timer is not a good class to use for this. You should take a look at AlarmManager and schedule your events using that.
You can use AlarmManager.set() to set a specific alarm, AlarmManager.setInexactRepeating() to set a repeating alarm that has some flexibility in terms of exactness, setRepeating() to set a precise repeating alarm.
In all cases you set up a PendingIntent that gets launched when the alarm fires, and your application should be prepared to handle that intent correctly.
Remember that you don't necessarily need to take action when that PendingIntent is fired: you can just check if the conditions are right (for example, you can add some logic as to whether the user should be notified or not at that point).
More about AlarmManager and PendingIntent:
http://developer.android.com/reference/android/app/AlarmManager.html
http://developer.android.com/reference/android/app/PendingIntent.html
Also, remember that you have to add a broadcast receiver to the "boot sequence completed" event so that you can reinstall your alarms after the device has been rebooted, since alarms don't persist across reboots.
I want to send data to server at some regular interval. So, I am using AlarmManager for the same. It works fine but the problem is that when I cancel the Alarm on Date/Time change. At that time Alarm fires again before getting cancelled, so that makes my application worse as an extra data is sent to server with irregular interval.
Here is my BroadCastReceiver class with AlarmManager.
public class MyReceiver extends BroadcastReceiver{
AlarmManager mgr;
PendingIntent pi;
Intent intent;
public static boolean flag = false;
#Override
public void onReceive(final Context arg0, Intent arg1) {
if(arg1.getAction().equals("android.intent.action.TIME_SET")){
Log.d("MyReceiver", "Time set");
mgr = (AlarmManager) arg0.getSystemService(Context.ALARM_SERVICE);
intent = new Intent(arg0, TestService.class);
intent.putExtra("test", "testvalue");
pi = PendingIntent.getService(arg0, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
if(!flag){
mgr.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 10000, 5000, pi);
flag = true;
}
else{
mgr.cancel(pi);
pi.cancel();
flag = false;
}
}
}
}
Below is the Screen Shot with Logcat output that explains that after cancelling the Alarm it fires once more time just after cancelling.
As you can see in the Logcat output black arrow shows where I changed that time to cancel the Alarm and red arrow shows that after cancelling the Alarm once again it fired just before cancelling which should not happen. So, can anyone give my idea why that is happening and what should I do to restrict Alarm getting fired again before cancelling.
NOTE:- This only happens when I tried to increase date/time say from 10:00 to 11:00, works perfect when I decrease time say 10:00 to 9:00.
Not able to see the LogCat at my end, but looking at the code, I am not sure, how is the Service which gets invoked (TestService) gets killed / stopped ? I think you would need to stop it somehow. Also, its not recommended to do long running tasks within the broadcast receiver.
Have you verified that you service stop event is occuring after the mgr.cancel(pi) is fired?
Just try with some unique code with pending intent within activity and then cancel that intent using the same code.
setting pending intent in activity
PendingIntent.getBroadcast(this, code, intent, PendingIntent.FLAG_UPDATE_CURRENT);
for stopping that broadcast receiver
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), code, intent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
why that is happening
First Thing is that you are using Intent Action android.intent.action.TIME_SET so It does mean that Everytime any how if the System date/time gets Changed your BroadcastReceiver will ne called Automatically.
Second you have used one static boolean flag in your Receiver class.
Now what is happening is Whenever you change your System timings the flag toggles it's state from false to true and from true to false.
That is what exactly happening in your code and logcat also shows the same that everything is working as per the code written.
So according to me there is nothing Wrong happening in the code and it's output.
what should I do to restrict Alarm getting fired again before cancelling
First thing as I think, you should not use Action TIME_SET like that to toggle flag on/off as users and developers might not remember for what they are changing time either to turn FLAG On or Off,
Better way is that,
you should handle the Service yourself by an Activity and show one ToggleButton there to manage the State of the FLAG and set and cancel the PendingIntent.
OR
And If you want to do the task of your service automatically then you just simply use the AlarmManager and set your Alarm Triggering time and Interval there only once say time is currenttime and Interval is 50000 miliseconds..
so it will obviously call the service from now onwards after every 5mins, then in your App you will only require one ToggelButton to indciate the Sync to ther server is On or Off , if user Toggle it on or off then write your AlarmManager code there in your Activity only in the toggleButtontb.setOnCheckedChangeListener(listener) , I suppose this is the better way then what you are actually implementing.
I don't understand what need to set the receiver for date change if your goal is only to send the data on server in some regular interval .
change date and time of device does not mean that your alarm wont work
at that time which you already have set before those changes .Alarmmanager work on that given duration of time which is excluding from local current date and time of device .
I am adding an event to my schedule
list and alarm has been fixed to that
event. I have to repeat alarm for
every one minute, from the before five
minutes of event ending time. In below
conditions I have to remove or cancel
alarm for particular event.
When I delete event from my schedule.
Event placed in schedules but I don't want alarm for event.
I am following concepts like sqlite database, Alarm manger, Services. I am confusing little bit using Services and pendingIntent. So, please suggest me the right way to approach my requirement.
You need to use the method cancel(...) from AlarmManager, using the same PendingIntent you used to set the alarm. Example:
this.getAlarmManager().cancel(mAlarmPendingIntent);
(this refers to the Activity or the Service from which you are cancelling the alarm).
Here is the link for the API.
Create the PendingIntent as:
mAlarmPendingIntent = PendingIntent.getActivity(this, requestCode, intent, flags);
The API doc for PendingIntent is here.