I need a service that should always be running till its stopped explicitly by my activity and should start again even if it is stopped due to some issue (START_STICKY flag). This service should continuously do something (every couple of seconds) using a TimerTask. I ended up with the following code.
public class SomeService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
TimerTask timerTask;
final Handler handler = new Handler();
Timer timer = new Timer();
#Override
public void onCreate() {
// code to execute when the service is first created
super.onCreate();
}
#Override
public void onDestroy() {
// code to execute when the service is shutting down
super.onDestroy();
}
#Override
public void onStart(Intent intent, int startid) {
// code to execute when the service is starting up
timerTask = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
//KEEP RUNNING SOME ERRANDS HERE
}
}
});
}
};
timer.scheduleAtFixedRate(timerTask, 100L, 1700L);
}
}
Is there anyway that I can optimize this to run continuously?
Running every second sounds pretty excessive, but is there a reason why you don't use the AlarmManager to trigger an IntentService? Then the system would be responsible for triggering your service reliably. Whether you can achieve reliable 1 second retriggers, I don't know. Seems like a bad idea for the reasons Mark is mentioning in the other answer.
Related
I am building a toast every 5 sec using some sample found.
The code works ok, but the service wont stop even i stopped the app.
Can anyone point out what is wrong?
public class MyService extends Service {
public static final long INTERVAL=5000;//variable to execute services every 5 second
private Handler mHandler=new Handler(); // run on another Thread to avoid crash
private Timer mTimer=null; // timer handling
#Nullable
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("unsupported Operation");
}
#Override
public void onCreate() {
// cancel if service is already existed
if(mTimer!=null)
mTimer.cancel();
else
mTimer=new Timer(); // recreate new timer
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(),0,INTERVAL);// schedule task
}
#Override
public void onDestroy() {
Toast.makeText(this, "In Destroy", Toast.LENGTH_SHORT).show();//display toast when method called
mTimer.cancel();//cancel the timer
}
//inner class of TimeDisplayTimerTask
private class TimeDisplayTimerTask extends TimerTask {
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
// display toast at every 5second
Toast.makeText(getApplicationContext(), "Notify", Toast.LENGTH_SHORT).show();
}
});
}
}
}
I keep receiving the toast Notify even the app had been closed.
add onTaskRemoved() method in your MyService,like this
#Override
public void onTaskRemoved(Intent rootIntent) {
stopSelf();///its will stop service
super.onTaskRemoved(rootIntent);
}
In your Activity onStop() you should call stopService(new Intent(context,YourService.class)); in order to stop your service
I'm currently working on my first android app and I've run into a problem.
My app is supposed to be counting in the background using a Service and I'm creating a new thread to handle that. If I don't stop the thread in my Service's onDestroy() method, my phone gives me the message "Unfortunately, (my app) has stopped." every time I close the app. I need to stop it somehow, and I tried to do it using :
while(!Thread.currentThread().isInterrupted()){
**my code**
}:
And then interrupting it in the onDestroy() method.
It works, but it makes my app count extremely fast, so I would like to know if it can be done any other way that does not change the functionaliy of my code.
Also, since my thread gets stopped in the onDestroy method, I guess my service stops as well. Is there any way to keep my service running even when my app has been closed?
Here's my code:
public class CounterService extends Service {
private Handler handler;
private int time = -1;
private boolean isActive;
private Intent timeBroadcaster;
private Runnable counter;
private Thread serviceCounter;
#Override
public void onCreate(){
super.onCreate();
handler = new Handler();
timeBroadcaster = new Intent();
timeBroadcaster.setAction("EXAMPLE_BROADCAST");
counter = new Runnable() {
#Override
public void run() {
isActive = ((PowerManager) getSystemService(Context.POWER_SERVICE)).isInteractive();
if (isActive) {
handler.postDelayed(this, 1000);
time += 1;
} else {
if (time > 5) {
//log
}
time = 0;
handler.postDelayed(this, 1000);
}
timeBroadcaster.putExtra("counter", time);
sendBroadcast(timeBroadcaster);
}
};
serviceCounter = new Thread(counter);
serviceCounter.start();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy(){
//serviceCounter.interrupt();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
Is there any way to keep my service running even when my app has been closed?
you can use sync adapter which runs in background even app is stoped.
https://developer.android.com/training/sync-adapters/creating-sync-adapter.html
I am making an Android app which runs a simple Service in the background.
Nothing fancy but the service toasts a msg every 5 secs confirming that it is running in the background, even when the App activity is terminated.
But when i checked the task manager, i found that the process is utilizing 4MB of ram initially but later keeps on increasing with time.
I want to know that if there is any way i can stop the extra memory usage and keep it to a bare minimum, since i know i am not doing any heavy work in the background.
Any help will be appreciated!
Thanks.
P.S. I will post the service code below.
public class BgmService extends Service {
public Handler mHandler = new Handler();
public BgmService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "Service has started!!!", Toast.LENGTH_SHORT).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mHandler.post(mtask);
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service was Killed!!!", Toast.LENGTH_SHORT).show();
mHandler.removeCallbacks(mtask);
}
public Runnable mtask = new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Service is Running!!!", Toast.LENGTH_SHORT).show();
mHandler.postDelayed(mtask, 4000);
}
};
}
As #PunK_l_RuLz told, your Runnable is getting created after every 4000 mili seconds. So, you can create a subclass of Runnable and use single object of this class for every Toast :
public class PostRunnable extends Runnable {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Service is Running!!!", Toast.LENGTH_SHORT).show();
mHandler.postDelayed(mRunnable, 4000);
}
}
Use above class like :
PostRunnable mRunnable;
if(mRunnable != null) {
mHandler.post(mRunnable);
} else {
mRunnable = new PostRunnable();
mHandler.post(mRunnable);
}
you are calling the mTask from inside your mTask, every time a new object of Runnable is created and as your Service holds the reference of every runnable object created your memory goes on increasing. I think using a Timer with TimerTask might solve your problem. Hope this helps
Have you tried using a timer instead of a post delay?
It's odd though, I can't see why it would leak.
I am writing app, which include service and timer. User set time of Timers. Timer must every day make work(even night). Timer (and service) is working when telephone active, but when telephone goes into sleep mode timer doesn't work(service still work).
May be I must use the Handler with timer how here: Android timer? How-to? or I must use PowerManager and forcibly not allowed to sleep telephone?
I use timer within service
public class SampleService extends Service {
....
public int onStartCommand(Intent intent, int flags, int startId) {
my_timer_start();
}
my_timer_start();{
ltimer = new Timer();
ltimer.scheduleAtFixedRate(new My_task(), time1, every_hour);
}
class My_task implements Runnable {
#Override
public void run() {
// TODO Auto-generated method stub
...........................
}
}
void cancel_task() {
ltimer.cancel();
ltimer = null;
}
public void onDestroy() {
super.onDestroy();
cancel_task();
}
}
thanks for the help!
My question is Android related:
How do I run a task every 20 seconds within an intentservice ?
Problem is, I have to init some classes which will be used in the Handler "run" process.
It works one time - but then the service stops & the application crashes when the handler-loop starts again after 20 seconds (probably because of the classes that got eliminated when the service stopped?). So maybe the solution is to get the service to stay running as long as the Handler runs or to throw away the code and do it right ?
Hope, someone can help me.
public class Fadenzieher extends IntentService{
private Handler handler = new Handler();
private Runnable timedTask = new Runnable(){
#Override
public void run() {
// My functions get called here...
// class1member.getDBWorkdone();
handler.postDelayed(timedTask, 20000);
handler.obtainMessage();
}};
public Fadenzieher() {
super("Fadenzieher");
}
#Override
protected void onHandleIntent(Intent intent) {
// SOME INITIALISING
// I have to init some vars & functions here that
// will also be used inside the handler loop
// Class1 class1member = new Class1();
// class1member.startUpDB();
handler.post(timedTask); }
Thank you very much in advance!!!
---- So this is the updated code now (14. nov. 2011)
public class Fadenzieher extends Service{
private static final long UPDATE_INTERVAL = 60000;
Context context = this;
private Timer timer = new Timer();
DbHelper dbHelper;
public void onCreate(){
dbHelper = new DbHelper(context);
runTheLoop();
}
protected void runTheLoop() {
timer.scheduleAtFixedRate(new TimerTask(){
#Override
public void run() {
dbHelper.dosomethings();
Toast.makeText(context, "CALL", Toast.LENGTH_LONG).show();
}}, 0, UPDATE_INTERVAL);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Starte Service“, Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent,flags,startId);
}
public void onDestroy() {
super.onDestroy();
dbHelper.close();
Toast.makeText(this, "Stoppe Service“, Toast.LENGTH_LONG).show();
}
// We return the binder class upon a call of bindService
#Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
public class MyBinder extends Binder {
Fadenzieher getService() {
return Fadenzieher.this;
}
}
}
The whole application crashes immediately.
How do I run a task every 20 seconds within an intentservice ?
That is not an appropriate use of IntentService. Use a regular Service, please.
It works one time - but then the service stops & the application crashes when the handler-loop starts again after 20 seconds
IntentService shuts down when onHandleIntent() returns, which is why this is breaking for you. Use a regular Service, please.
Also:
Please allow the user to configure the polling period
Make sure that this service will shut down when the user no longer wants it to be running