The doco for startService states "If this service is not already running, it will be instantiated and started (creating a process for it if needed); if it is running then it remains running."
I'm finding that each call to startService appears to be starting a separate instance of the service, in that the work that the service is doing (in my test case, trivially writing to a new log file) is being done again for each call.
I'm trying to detect the service by looping through ActivityManager... getRunningServices(Integer.MAX_VALUE)) but it's not showing up.
Android 2.3.3 on SGS 11
I'm missing something here. I understood that the Service's onCreate() method only gets called when it's created, and that since I have a continuous process running in the Service (the
In my Activity's onResume method I'm starting the service ("myService")with:
Intent intent = new Intent(this, myService.class);
startService(intent);
In MyService I have an onCreate like
#Override
public void onCreate(){
super.onCreate();
...
from where I set a timer, using a TimerTask, which writes to a log file once/second.
This works as expected - I can see the log being written.
In the Activity's onResume method, before calling the StartService method, I'm checking to see if the myService service exists by calling a checkForRunningService method containing
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (service.service.getClassName().contentEquals("com.gpsanimator.startrax.myService")) {
Toast.makeText(getApplicationContext(), "Service IS SO running: ", Toast.LENGTH_SHORT).show();
return true;
}
This never finds the myService service, even though it appears to be running as it's happily writing to the log file.
Eeach time I resume my Activity, the onCreate method of my myService service gets called - it generates a new log file and starts writing to it as well as the original log file being continuously updated.
Doesn't the Service get started the first time the startService is called? And then continue running? Shouldn't subsequent calls to startService() find the Service already running and therefore not trigger the onCreate() method again? But that's not what I'm seeing. It seems that every call to startService() is triggering the Service's onCreate() method.
It's obviously more complicated than this, and I would like to get to the bottom of it.
It all depends on which method you're putting the code in.
When you call startService only one service will be created at a given time. If the service already exists it will be reused. So the code in onCreate() will only be called if a service did not already exist.
However, each time you call startService the code in onStartCommand() will be run no matter what.
So yes only one instance of a service ever exists at a given time, but calling startService can have an effect.
The problem was I had declared my myService class to extend IntentService, not Service!
Once I fixed that, it all worked as per the book!
IntentService stops immediately (automatically) after work is performed, BUT if you start it again till work finishes you are reused existing service instance and onCreate isn't called. So please be careful with IntentServices.
You are extending IntentService which will work as a worker thread. The service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work. So in your case your service stop itself after completing the task so it creates multiple times. You should use Service class and bind with the component.
Related
I am using the following statement to stop a download service (that extends IntentService) running in the background:
context.stopService(intent);
But this statement is not calling the onDestory() method of service immediately, It is taking sometime to call onDestroy() method of service.
#Override
public void onDestroy() {
Log.d("JSLog", "on destroy called");
super.onDestroy();
}
What should I do that after hitting the stopService() statement, it should immediately called onDestroy() method of the service.
In my case, I followed the tutorial at Android Developers, which uses a ServiceConnection. In the example code, they call unbindService() but never stopService(). So I added a call to stopService() to stop it, but still onDestroy() never got called.
From the documentation of Context.stopService():
Note that if a stopped service still has ServiceConnection objects bound to it with the BIND_AUTO_CREATE set, it will not be destroyed until all of these bindings are removed.
I interpreted this as it's okay to call stopService() or stopSelf() first, and then unbindService() afterwards (I'm using BIND_AUTO_CREATE) - and that the service would be stopped/destroyed upon calling unbindService().
But it turns out that this isn't the case. When I moved things around so that I'm calling unbindService() first and stopService() after that, my onDestroy() gets called immediately.
the intentService has new Thread,when u stop the service the new thread won't stop right now,if u want stop the thread right now ,i will extends service and new Thread in the service,when u need stop the service just need interrupt the thread.
This is expected behaviour, a Service won't immediately be destroyed once stopped just like an Activity might not be immediately destroyed once finished (unless you finish inside onCreate).
I'm facing a strange problem with my app. I have a LocationService that runs in the background. The way I manage its lifecycle is:
In onResume, every activity uses bindService(intent,serviceConnection, BIND_AUTO_CREATE) like that the service is automatically created when needed.
In onStop, every activity uses unbindService(serviceConnection)
This works because when switching activities, the new Activity onResume is called before the old Activity onStop method
The problem I have is, lets say I start from the home screen and I launch the app with an Activity that has a fragment in it. The order of the function call is as follows
Activity onCreate --> setContentView is called here
Activity onResume --> here bindService is called and should create the Service
Fragment onResume
Service onBind method is called
My question is why is there a something else between my bindServiceand onBind calls?? I have a feeling this has something to do with threading issues.
Well, this isn't a very good answer, but why wouldn't there be something else between your bindService() and onBind() calls? You seem to be assuming that when you call bind the system will immediately create and start your service, and no such guarantee is provided.
You haven't indicated whether yours is an IntentService, or just a regular Service, and this might affect the speed with which your service is launched, but my answer would be the same.
Also, I'm assuming that your ServiceConnection object is called, as expected, sometime after your service's onBind() returns.
I say this not based on having read anything definitive, but because I had a similar experience: I was surprised and annoyed at how long it took before my service was created and my ServiceConnection was called, even though I returned from the service's onBind very quickly. (My fragments needed data from the service to create the initial UI so any delay in the creation of the service meant a delay in displaying the initial UI to the user.)
In the end I settled upon launching my service using an Intent rather then a bind, e.g.
Intent si = new Intent( this, com.company.MyService.class );
si.setAction( MyService.SVC_BIND );
startService( si );
I then sent MyService.SVC_UNBIND in place of calling unbind. When I received the UNBIND intent in my service I cleanup and then call stopSelf(). These are user actions - I just named them for how I'm using them.
I believe this was faster, but looking back upon my comments from that code I don't have any specifics. Note that this meant no ServiceConnection, but I'm making some direct calls from the activities into the service, and using LocalBroadcastManager a fair bit.
Another option to consider (in order that your service be started more quickly, if that is your goal here??) is to launch it in Appliction.onCreate(), rather then waiting for Activity.onResume(). All of these options make it necessary to do some extra work to determine when to stop the service, compared to your current, normal, scheme where that is taken care of for you.
In my case, my issue was using android:process attribute for <service> element within Android Manifest, which is supposed to improve performance, but in reallity, maybe it does once the service is running, but it takes a very long while to reach onCreate() (and so also to reach onBind()). For me it was taking minutes. Now Apps and services run smooth and as expected.
More info:
https://developer.android.com/guide/topics/manifest/service-element
Usually when I create an Android service I implement the onCreate method, but in my last project this does not work. I tried implementing onStartCommand, and this seems to work.
The question is: when I have to implement a service which method is required? Which methods I have to implement? onCreate, onStartCommand, or both? And what is the role of each?
onCreate() is called when the Service object is instantiated (ie: when the service is created). You should do things in this method that you need to do only once (ie: initialize some variables, etc.). onCreate() will only ever be called once per instantiated object.
You only need to implement onCreate() if you actually want/need to initialize something only once.
onStartCommand() is called every time a client starts the service using startService(Intent intent). This means that onStartCommand() can get called multiple times. You should do the things in this method that are needed each time a client requests something from your service. This depends a lot on what your service does and how it communicates with the clients (and vice-versa).
If you don't implement onStartCommand() then you won't be able to get any information from the Intent that the client passes to onStartCommand() and your service might not be able to do any useful work.
Service behave same like Activity Whatever you want to associate once with a service will go in onCreate like initialization
and whenever the service is called using startService. onStartCommand will be called. and you can pass any action to perform . like for a music player , You can play ,pause,stop using action
And you do any operation in service by sending an action and receiving it on onStartCommand
onCreate work like a Constructor.
Edit in Short
onCreate() calls only for the first time you start a Service Whereas onStartCommand() calls everytime you call the startService again. It let you set an action like play,stop,pause music.
public void onStartCommand()
{
if(intent.getAction.equals("any.play")
{
//play song
}
else if(intent.getAction.equals("any.stop")
{}
}
I've got a service that is running in a separate process. I'm finding that after the main process UI thread exits from onDestroy() that my service is being destroyed even though I've provided the application context with the binding and specified BIND_AUTO_CREATE.
In my main process' UI thread onCreate() I've got this binding code:
Intent intent = new Intent(mAppContext, MyService.class);
mAppContext.bindService(intent, mMyServiceConnection, Context.BIND_AUTO_CREATE);
In my main process' UI thread onDestroy() I've got this unbinding code:
mAppContext.unbindService(mMyServiceConnection);
Note that I never call stopService().
Android's documentation for bindService() says:
The service will be considered required by the system only for as long as the calling context exists.
If I'm reading that correctly, because I supplied the application's context, the service is considered required by the system for the life of the application.
I have thought that maybe the application's context dies with onDestroy(). This is what Android's documentation says for getApplicationContext():
Return the context of the single, global Application object of the current process.
If the application's context dies with onDestroy(), then I think Android has a big issue. The issue is that when the display is rotated, onDestroy() is called (and immediately followed by onCreate()). Thus the effect is that when the display is rotated -- and it occurs quite frequently in my case! -- my service always exits.
Note that the pid of my app's process never changes, i.e. it is the same process. That is important in light of the documentation for getApplicationContext() stating "current process."
Here are what my debug logs show:
04-03 05:15:12.874: DEBUG/MyApp(841): main onDestroy
04-03 05:15:12.895: DEBUG/MyApp(847): service onUnbind
04-03 05:15:12.895: DEBUG/MyApp(847): service onDestroy
04-03 05:15:12.934: DEBUG/MyApp(841): main onCreate
04-03 05:15:12.966: DEBUG/MyApp(847): service onCreate
04-03 05:15:12.975: DEBUG/MyApp(847): service onBind
So my questions are:
1) Is my understanding about binding/unbinding correct?
2) Is there a way to have my service not get destroyed when UI thread's onDestroy() is called?
A hack for question #2 is to never unbind. But I don't like it because then I am leaking a binding every time onDestroy() is called. I could "remember" that I've got one leaked binding, and leak just that one, but then I've got cascaded hacks and it's real ugly.
1) Yes, I think your understanding is correct (I say I think because I think I understand what you're saying ;-) ). The flag you are using means "start this service automatically if somebody tries to bind to it and keep it running as long as somebody is bound to it, but once nobody is bound to it, feel free to kill it".
2) Check out the START_STICKY flag as described here. That should allow you to start the service and keep it running regardless of what happens to the calling Context
In general, onDestroy() means your activity is about to be killed. When you rotate the display, the Activity is killed and recreated. You are responsible for saving any state to the Bundle in the appropriate method and then restoring it in onCreate().
Does your service get killed:
if there is a second Activity on the stack?
if you handle configuration changes?
Why do you need your service to stay alive after your application has been destroyed?
I think the general rule of thumb is that you can't be sure when your activities and services will be killed. If this is blocking something you're trying to achieve, there may be a clever way around it.
Edit - you can actually handle the orientation configuration change so that your activity isn't restarted. For more info see the second half of this answer.
About the "second" Activity: Image you start activity A and then activity B. Now you rotate the screen while B is showing, causing B to restart. Will A be restarted at this point? I'm not sure, but I have a hunch that A will tend to stay alive and keep your application alive during the orientation change. This might be another strategy for keeping your service alive if that's what you're aiming for.
a service is destroyed only when both of the following are true:
All calls to bindService() have been matched by corresponding calls to unbindService().
If somebody called startService(), somebody also called stopService() or the service called stopSelf().
A service can be both started and have connections bound to it. In such a case, the system will keep the service running as long as either it is started or there are one or more connections to it with the Context.BIND_AUTO_CREATE flag. Once neither of these situations hold, the service's onDestroy() method is called and the service is effectively terminated.
this gives a great solution which is also fairly correct and safe!
say there are 2 activities ('viewer' and 'chat' in this example) that need a service, if both bindService AND startService. Also using the binder they update 'viewer_connected' and 'chat_connected' during onStart and onStop.
Then the service runs a loop in a thread that does this:
public isRunning = true;
while (isRunning) {
if (viewer_connected) {
// send update to viewer activity
}
if (chat_connected) {
// send update to chat activity
}
try {
Thread.sleep(5000);
} catch (Exception e) { isRunning=false; }
// 3 second timeout before destroying service
if (!viewer_connected && !chat_connected) {
try { Thread.sleep(3000); } catch (Exception e) { isRunning=false; }
if (!viewer_connected && !chat_connected) isRunning=false;
}
}
stopSelf();
This works because it needs both the activities to unbind AND the service to stopself() before it destroys the service, meaning there is a timeout before the service gets destroyed.
I Need some help here, I have a service which I can start or stop whenever I want and using the onStart() command to pass some extras using putExtras() from my activity
But I need some serious basic instructions on how to interact with the already created service.
Please don't refer me to another webpage which already have some implementations, just give me the needed code to interact from my UI activity to the service:
something like this:
public class myActivity extends Activity {
Object ReceivedObjectFromService;
onCreate()
{
some stuff here
myMethod()
}
public class myMethod()
{
//do some stuff with the ReceivedObjectFromService
//Don't know how to call this method from the service btw
}
please some help, I don't understand the tutorials on how to interact service to activity or viceversa
Interaction with already created service is no different to starting a brand new service. You just simply call startService() so your client code is no different.
Now, the part which is different is the service itself. In your service, onCreate() must start a background thread or a timer to carry on doing a work. onStart() will receive all startService cases and must in fact add the data it receives in the Intent to an internal list or queue and then in the timer's callback start processing from this queue.
Now you can pass any messages or data you want (even closing the service) using startService and passing data in the Intent that your service understands.
Hope this helps.