How to schedule an android service to execute at a fixed rate - android

I am working on an application that should download a file from the network every X seconds to check for any change, I use a service to do that, but its execution is not fixed with the delay time rate, here is my code for the service:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
checkUpdate();
return START_STICKY;
}
private Void checkUpdate() {
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
Log.i("Service", String.valueOf(++counter));
if(Helper.isNetworkAvailable(getBaseContext())) {
// download file
} else {
Log.e("ServiceHandler", "Couldn't get any data from the url");
}
}else {
Log.e("Connection", "No connection");
}
}
}, 10000, 10000);
return null;
}
The output isn't fixed, it is supposed to run every 10 seconds, while running the service run in a random manner

How about setting up an AlarmManager within an IntentService? Much more accurate.
Intent intent = new Intent(context, YourClass.class);
PendingIntent pi = PendingIntent.getService(context, 0, intent, 0);
AlarmManager am = (AlarmManager) c.getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC, System.currentTimeMillis(), 10*1000, pi);
Make sure within YourClass.class (which is an IntentService), put your logic in the handleIntent(Intent intent), which will be called every 10 seconds by the PendingIntent sent by the AlarmManager.
P.S. Update your manifest
Hope it helps

Instead of Timer Class, use AlarmManager class. It also performs the same repeating tasks you want. AlamrManager is light weight and it runs even if your device is in sleep mode.
Also see this link Android: How to repeat a service with AlarmManager

For repetitive jobs android provides simple api, called Timer please look it. Very simple to use.

Try this :
#Override
public void onStart(Intent intent, int startId) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Log.d("Internet Available: ", ""+flag);
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 10);
Intent intent1 = new Intent(this, UpdateWidgetServiceDemo.class);
PendingIntent pintent = PendingIntent.getService(this, 0, intent1, 0);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
int i;
i=15;
alarm.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pintent);
super.onStart(intent, startId);
}
REMOVE return START_STICKY;

Related

how can I set repeating alarm every 5 second to show message

here is my code in application class inside oncreate method: But I can't see any message from my app. Can anyone help me to do this?
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
public void startAlarm() {
manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
int interval = 5000;
manager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);
Toast.makeText(this, "Alarm Set", Toast.LENGTH_SHORT).show();
}
And on the broadcast receiver class I have the following code
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent arg1) {
// For our recurring task, we'll just display a message
Toast.makeText(arg0, "I'm running", Toast.LENGTH_SHORT).show();
}
}
Edited answer:
Use setInexactRepeating() instead of setRepeating(). setRepeating only takes set intervals with the shortest being INTERVAL_FIFTEEN_MINUTES. setInexactRepeating() is the only way to set a repeating interval as short as 1000ms, or 5000ms in your case.
Change:
manager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);
to
manager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);
If you are not getting the exact 5 second delay that you need, you will need to use a Handler. Any type of alarm with a 5 second delay will not work properly because as of Android 5.x basically all repeating alarms are inexact to save battery life.
I have modified your code to use a Handler:
startAlarm();
public void startAlarm() {
final Handler h = new Handler();
final int delay = 5000; //milliseconds
h.postDelayed(new Runnable(){
public void run(){
//do something
Intent alarmIntent = new Intent(getApplicationContext(), AlarmReceiver.class);
sendBroadcast(alarmIntent);
h.postDelayed(this, delay);
}
}, delay);
}
That alarm method will work with your current BroadcastReceiver and do an actual 5 second delay.

Starting service with Alarm Manager on Android?

Hi a read other question retated to this but the responses never resolve my issue.
I want to start a service after a specific time with an Alarm Manager
alarmMgr = (AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmServiceIntent=new Intent(ListActivity.this, AlarmLevelServiceImproved.class);
alarmServiceIntent.putExtra("username",usernameID);
alarmServiceIntent.putExtra("password",userPass);
alarmIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, alarmServiceIntent, 0);
. . .
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND,10);
//calendar.set(Calendar.HOUR_OF_DAY, 19);
//alarmMgr.setInexactRepeating(AlarmManager.RTC,calendar.getTimeInMillis(),
// AlarmManager.INTERVAL_HALF_HOUR,alarmIntent);
//alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
// 1000 * 10, alarmIntent);
alarmMgr.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), alarmIntent);
Log.d("MioLog", "Alarm setted");
My service is:
public class AlarmLevelServiceImproved extends Service {
#Override
public void onCreate() {
Log.d("MioLog","MyAlarmService.onCreate()");
Toast.makeText(this, "MyAlarmService.onCreate()", Toast.LENGTH_LONG).show();
}
#Override
public IBinder onBind(Intent intent) {
Log.d("MioLog","MyAlarmService.onBind()");
Toast.makeText(this, "MyAlarmService.onBind()", Toast.LENGTH_LONG).show();
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("MioLog","MyAlarmService.onDestroy()");
Toast.makeText(this, "MyAlarmService.onDestroy()", Toast.LENGTH_LONG).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MioLog","MyAlarmService.onStart()");
Toast.makeText(this, "MyAlarmService.onStart()", Toast.LENGTH_LONG).show();
return super.onStartCommand(intent, flags, startId);
}
}
And I add this on AndroidManifest.xml (The service class is on the sub-package "services"):
<service
android:name=".services.AlarmLevelServiceImproved"
android:enabled="true" />
But the service don't start and no log is printed.
Any idea how to start a Service with the AlarmManager?
I also suived this tutorial but I don't find any difference to my code
Thanks
To start a service with a PendingIntent, you need to use the static method PendingIntent.getService() to retrieve the appropriate PendingIntent.
Your code seems to be using PendingIntet.getBroadcast() for whatever reason. If you intend to have the AlarmManager indeed send a broadcast, you can start your service in your BroadcastReceiver, else change that line to getService():
from
alarmIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, alarmServiceIntent, 0);
to
alarmIntent = PendingIntent.getService(getApplicationContext(), 0, alarmServiceIntent, 0);
You are using getBroadcast() to create the PendingIntent, but the Intent points to a service. That combination will not work.
Since you are using RTC_WAKEUP, you need to use getBroadcast() and a WakeLock to get reliable results. One approach is to use WakefulBroadcastReceiver as the base class of your receiver, where you then forward the work onto an IntentService.
Also, please do not pass user names and passwords in extras, as those are visible to anything that gets its hands on the Intent or PendingIntent. In this case, that should just be your app and the core OS, but I would still aim to do something a bit more secure.

Stop the background service after particular time in android

Hi i need to stop the Background service which is already started after particular time.I will get the duration from server for when to stop the service.I have tried the Alarm Manager in android.
Calendar cal = Calendar.getInstance();
Intent intent = new Intent(context, MyService.class);
PendingIntent pintent = PendingIntent.getService(context, 0, intent, 0);
AlarmManager alarm = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
// Start every 30 seconds
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 60*1000, pintent);
Log.e(TAG, "Service started in Activity");
This above code is starting the service after every one minute.But i dont want to start the service.I need to stop the service after a minute.How to do that.Is that possible to do with Alarm Manager.Please guide me.
Try that:
add parameter to your pendingIntent
Intent intent = new Intent(context, MyService.class);
intent.putExtra("param_name", "end");
PendingIntent pintent = PendingIntent.getService(context, 0, intent, 0);
Override onStartCommand() method in your Service
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try{
String parameter = intent.getStringExtra("param_name");
if(parameter.equals("end")){
stopSelf();
}
}catch(Exception ex){
}
}
Also you can try to use Handler in your service:
Handler variable:
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1: {
stopSelf();
}break;
}
}
}
Delayed task:
handler.sendEmptyMessageDelayed(1, 60 * 1000);
Create the timer task to stop the service and assign the delay time which you are getting from your server
Timer timer = new Timer ();
TimerTask hourlyTask = new TimerTask () {
#Override
public void run () {
// your code here to stop the service ...
}
};
// schedule the task to run assign the time (DelayTime) which you are getting from server
timer.schedule (hourlyTask, DelayTime);
So what is the particular time.
You can do 1 thing make note of the starting time of the service. and if you want to stop the service after a specified duration or the specific time get the system current time compare it with that time if it match's stop the service. this should resolve the problem.
Tell me if it works for you..
======>
Just Follow the steps provided steps below:
Use sharedprefrence to save the start time of the service.
If your not familiar to shearedprefrence URL:http://examples.javacodegeeks.com/android/core/content/android-sharedpreferences-example/
Then in the service onStart method get the system current time if it
matches the time stop the service.
You have to create an broadcast receiver:
Calendar cal = Calendar.getInstance(); // this will return current time
// if you want to trigger after 1 minute then add into calender object
cal.add(Calendar.MINUTE, 1);
Intent intentAlarm = new Intent(this, AlarmReciever.class);
intentAlarm.setAction("My_Action");
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
MainActivity.this, REQUEST_CODE, intentAlarm,
PendingIntent.FLAG_UPDATE_CURRENT);
// set the alarm for particular time
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);
AlarmReciever .java
public class AlarmReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// call method to stop service
}
}
Also declare this AlarmReceiver class in menifest file
<receiver android:name=".AlarmReciever" >
</receiver>
> here i used the countdowntime for 30second
after 30second call stopself() method it will stop your
services..u can also do what ever u want on finsih you can also pass a
notification to the user....
new CountDownTimer(30000, 1000) {
#Override
public void onTick(long l) {
}
#Override
public void onFinish() {
//r u can also pass a notification
stopSelf();
}
}.start();

AlarmManager on being cancelled immediately invokes pending intent

So I have a section of code that schedules an alarm as follows
public void scheduleAlarm(){
Log.d("Scheduler","Alarm is being scheduled");
Intent intent = new Intent(AlarmSettings.this, VolumeService.class);
intent.putExtra("MODE", mode);
PendingIntent pintent = PendingIntent.getService(AlarmSettings.this, id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Log.d("Alarm ID:", String.valueOf(id));
Log.d("Time", "Time was set for today: " + String.valueOf(time));
if(time < System.currentTimeMillis()){
time += (DAY);
Log.d("Time", "Time was set for tomorrow: " + String.valueOf(time));
}
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm.set(AlarmManager.RTC_WAKEUP, time, pintent);
}
The service that is being called is as follows
public class VolumeService extends Service{
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//My Service code goes here and makes changes to some settings
Log.d("Service", "settings have been changed");
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
and finally the portion of code that is supposed to cancel the alarms (stay with me, I know its lengthy)
//Unschedule the alarm that is getting deleted
Log.d("Unscheduler", "Alarm is being unscheduled");
Intent uIntent = new Intent(AlarmSettings.this, VolumeService.class);
PendingIntent uPintent = PendingIntent.getService(AlarmSettings.this, id, uIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager uAlarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
uAlarm.cancel(uPintent);
uPintent.cancel();
Now, my problem is that when the user deletes an alarm and subsequently calls the unschedule portion of the code, the volumeService is immediately called and the settings are changed. However, this defeats the purpose of the user deleting the alarm as they will only delete it to prevent it from firing and changing the settings. I have checked everywhere imaginable over the course of weeks and am just beating my head against the wall. Now that I have posted it on here though, it will be that I have made a very simple mistake. In any case, thanks for the help in advance!
--edit #1--
Removed the line uPintent.cancel() in the unscheduler portion and still doesn't work.

crash (or automatic restart) of service

I've a service that runs after the Android devices boots up. This executes two notifications every day. But I've a problem: It looks like the the service crashes or automatically restarts. Also the notifications are not executed at the specified time. How can I fix this? Sometime I see the toast Service Created and Service Started. Thanks!
The code:
public class UnUsedService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "Service Created", Toast.LENGTH_LONG).show();
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
private PendingIntent pendingIntent;
#SuppressWarnings("deprecation")
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
Calendar cal1 = Calendar.getInstance();
cal1.set(Calendar.HOUR_OF_DAY, 05); //midday
cal1.set(Calendar.MINUTE, 45);
cal1.set(Calendar.SECOND, 00);
Calendar cal2 = Calendar.getInstance();
cal2.set(Calendar.HOUR_OF_DAY, 17);//8pm for example
cal2.set(Calendar.MINUTE, 30);
cal2.set(Calendar.SECOND, 00);
AlarmManager am = (AlarmManager)getApplicationContext().getSystemService (Context.ALARM_SERVICE);
Intent intent2 = new Intent(getApplicationContext(), AlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(), 0, intent2, PendingIntent.FLAG_UPDATE_CURRENT);
am.setRepeating(AlarmManager.RTC_WAKEUP, cal1.getTimeInMillis(),cal2.getTimeInMillis(), pi);
}
};
If your notices need to run at a particular time, you should be using AlarmManager to schedule them. This gets retained by Android, so that your service is free to be killed and the alarm will restart it when necessary.
It sounds like you're currently letting your service run 24/7 just so that it can do something twice a day; this is being a bad Android citizen! Using the AlarmManager instead will fix your problem and also let you stop wasting resources.

Categories

Resources