I've created a custom Background Service, who is extending IntentService. I'm calling this class when my app goes to background via .startService(). Firsly onStartCommand is called where I'm returning START_STICKY (like I've read some other posts to keep my service alive and re-create if needed when is killed due to low memory). After that I'm implementing onHandleIntent(intent) method where I'm getting the extras from the caller intent and here I'm starting a Timer to run every minute and execute simple code. But the problem here is that, when the app is in background, after 30 mins my service is killed and not re-created. Here is part of my code, so any suggestions would be perfect.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
#Override
protected void onHandleIntent(Intent workIntent) {
//here I'm initializing the Timer
}
class UpdateTimeTask2 extends TimerTask {
public void run() {
backgroundTimer();//here I'm doing some simple coding
}
}
So, as Kumar said, i should extend Service not IntentService. Calling of the service was the same as calling of the IntentService, the only difference was the unimplemented methods that were required by the Service class. Also I'm using Handler's postDelayed method instead of Timer and also in onStartComand I'm returning START_STICKY. So the service is not killed at all. Useful code can be found here and here. I hope this helps.
In this case a normal Service and a Handler should be all you need. As Pankaj wrote IntentServices are not designer for longrunning operations. You can then use the Handler's postDelayed method to excecute your code every minute.
Related
I am trying to understand the Service Life Cycle while working through some Android Open Source Code.
I was looking at a Service implementation which I distilled down to something like the following...
public class MyService extends Service {
public MyService() { super(); }
#Override
public void onCreate() {
super.onCreate();
init();
//==this seems odd to me
//comment in AOSP says startService() is called to make
//sure Service stays around long enough for the async call
//to complete.
startService(new Intent(this, myservice.class()));
doSomeMoreInitAsync();
}
#Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
if(actionableIntent(intent,flags,startId)) {
//do something
//NOTE: the Intent passed to startService() in onCreate()
//above will go around this block of code, doing nothing
//except returning START_STICKY
}
return START_STICKY;
}
public void onDestroy() {
//destroy stuff
}
#Override
public IBinder onBind(final Intent intent) {
return mBinder; //an instance of android.os.Binder derivative
// created when this service was instantiated
}
//other stuff
}
Why would someone want to have onCreate() call startService() on itself like above, doing nothing? The comment in code sheds some light, but it's like assumptions are being made about the Life Cycle that I don't understand. I.e., is it reasonable to expect onCreate() to effectively start its own service?
I know that if a service has already been started then onCreate() will only be called once (unless destroyed and restarted, then a new instance of the service is created and onCreate() is called once on it). My first concern with this example would be that there is an expectation placed upon the underlying Service API implementation that the Service is already in the initialized state before onCreate() is called (else there be an infinite recursion, but there is not).
But isn't onCreate() supposed to be part of the initialization (albeit an optional part for the subclass)?
Is this coding logic a reasonable way of making sure the Service is forced to be an Unbounded Service? Or am I looking at a bad example in the AOSP which may have undefined behavior in the future?
You are correct in that a Service will call onCreate and onStartCommand if it is started via Context.startService. So in this sense, when you return START_STICKY, the Service will continually run until an explicit call to stopService() is called. It will also be destroyed and restarted during this lifecycle.
Another way to create a Service, is by binding to it. As per the docs:
Clients can also use Context.bindService() to obtain a persistent connection to a service. This likewise creates the service if it is not already running (calling onCreate() while doing so), but does not call onStartCommand().
So, it's possible for a Service to be created by simply binding to it. However, the lifecycle of a Service indicates that it will remain if it is started or a client is still bound to it. Meaning, that if it was created by a bind command, it will immediately be destroyed as soon as the client unbinds.
So, if a Service starts itself in the onCreate(), it will ensure that it puts itself in the started state regardless of whether it was created by binding or by an explicit call to startService. Since there's no actionable intent, the onStartCommand will just pass straight through. An clients that call startSevice will, presumably, have actionable Intents in which case the Service will perform its duties.
I'm reading the official documentation about Services, but I'm a little bit confused because some things aren't so explicit.
Let's take this snippet:
public class MyService extends Service {
public int onStartCommand(Intent intent, int flags, int startID) {
while(...any condition...) {
//some actions
}
return START_SOMETHING;
}
public IBinder onBind(Intent intent) {
return null;
}
}
My doubts are the followings:
The Android system can destroy a service not bound to the current focused activity and not declared as in foreground. But can the Android system destroy a service even if it is still in the while loop?
When I call stopService() does it wait for the onStartCommand() to get to the return statement?
Where should I insert the stopSelf() call? Just before the return statement?
Can the Android system destroy a service even if it is still in the while loop?
Yes. For some reason, extreme low memory pressure (for example), Android system kills the Service without calling onDestroy() method. Why? Because of Service always runs on UI thread.
When I call stopService() does it wait for the onStartCommand() to get to the return statement?
No. Return statement's action will be executed when Android system kills the Service. But, if you call stopSelf() manually, the return statement's action will be ignored.
Where should I insert the stopSelf() call? Just before the return statement?
Call stopSelf() wherever and whenever you want. For example, if user press a button, call stopSelf() to stop the Service playing a music.
In my application I have an activity and a service (extends IntentService ). the service's onStartCommand looks like below
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_REDELIVER_INTENT;
}
My onHandleIntent method:
#Override
protected void onHandleIntent(Intent intent) {
while(continueLoop){ //continueLoop is controlled by the Binder
//Do stuff
}
}
I also bind to the service from activity, so I can break the infinite loop. I started the app and it's service, and then started other applications, after a while my Activity got stopped and destroyed, so is my Service. When I close the other applications using task manager , the service doesn't start by itself.
I waited and then launched my app, as soon as activity is launched service also started. I thought the android system will restart the service automatically when memory is available. Am I missing something or should i wait longer.
Thanks in advance
If you read this IntentService you'll see that
onStartCommand(Intent intent, int flags, int startId)
You should not override this method for your IntentService.
Instead
The IntentService class exists to simplify this pattern and take care of the mechanics. To use it, extend IntentService and implement onHandleIntent(Intent).
Per the IntentService documentation:
Clients send requests through startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.
If you are binding to the Service and/or controlling the lifecycle of the service yourself, then you should use a Service and not an IntentService.
I have an Android application that has a button that starts the service.
Here is the service:
public class SimpleService extends Service
{
#Override
public int onStartCommand(Intent intent,int flags, int startId)
{
Toast.makeText(this,"Service Started",Toast.LENGTH_SHORT).show();
Integer i=0;
while (i<10)
{
Log.d("Hi",i.toString());
SystemClock.sleep(5000);
i++;
}
Log.d("Hi","return START_STICKY");
return START_STICKY;
}
public void onDestroy()
{
super.onDestroy();
Toast.makeText(this,"Service Stopped",Toast.LENGTH_SHORT).show();
}
}
When I clicked on the button, the service starts successfully, but after some while, in the emulator, I got an error like
Application is not responding. Would you like to close it?
Am I doing anything wrong in service implementation?
What I want to do is perform a task on every 5 seconds even if my application got killed.
I tried with IntentService but it got killed when my app got killed so my task remains incomplete.
while (i<10)
{
Log.d("Hi",i.toString());
SystemClock.sleep(5000);
i++;
}
I would like to point out this part of your code. Here what you are doing is once your service starts, you are doing 10 iterations of loop and in each iteration you are pausing execution for five seconds (which is a lot of time in terms of execution). As services run in the main process, in my opinion, they block the main thread, which means during the sleep, if your app is accessed, you will get the ANR (App not responding) error. Thus, these types of tasks should be run in a separate thread.
If you want to perform some repetitive tasks on the background, I'd suggest you make use of a AlarmManager component of the Android SDK.Alarm manager is a system service, thus you can access it by using the following line of code.
AlarmManager mAlarmMgr=(AlarmManager) getSystemService(Context.ALARM_SERVICE);
//Then you can set alarm using mAlarmMgr.set().
You will then receive the alarm in a AlarmReceiver.
AlarmReciever class extends BroadcastReceiver and overrides onRecieve() method. inside onReceive() you can start an activity or service depending on your need like you can start an activity to vibrate phone or to ring the phone.
I hope this helps. Cheers!
Since By Default, all your app components (like Activity, Service etc) runs in Main/UI Thread, and if it get blocked, Android shows ANR dialog.
Also, Each of lifecycle method of service is called from UI thread. If you need background task to be running all the time, you can crate new thread for this.
You may try below code inside your Service class:
new Thread(new Runnable(){
public void run() {
while(i<10)
{
Thread.sleep(5000)
//REST OF CODE HERE//
}
}
}).start();
Does anyone know if there is a way of stopping an IntentService without it finishing its work thread and stopping itself?
Simple question, but I couldn't find the answer in the documentation. Is there a simple way of stopping it?
Thanks
bevor a message to a service is enqueued onStartCommand is called. which forwards the message for queueing. so you could just override onStartCommand, something like that:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction().equals("Stop"))
stopSelf();
onStart(intent, startId);
return START_NOT_STICKY;
}
cheers
You should be able to call stopSelf();
http://developer.android.com/reference/android/app/Service.html#stopSelf()
I currently stumble upon this requierement for an app i am working on. I will try using onStartCommand to send a message to the Intent Service to stop working (for example, setup a boolean flag stopWork = true) and evaluate it during the working job or before the next queued task. The IntentService wont stop inmediately but will skip all pending tasks. Hope it helps. Gonna try it myself also.