I have a service with a content observer watching the calendar provider and there are some instances where i need to stop the service so the observer's onchange does not get called when adding an event and then restart the service when it is added.
In my activity I use stopService(new Intent(context,Service.class)); to stop the service then I start it up again later on trying to avoid the onchange call when the provider gets changed but it does not appear the service gets stopped because the onchange still gets called causing force closes in my database because my query in my service cant find the event yet.
so how can i get around this problem?
Try like this:
ComponentName service = startService(new Intent(this, BaseballWatch.class));
// Stop a service using the service name.
stopService(new Intent(this, service.getClass()));
// Stop a service explicitly.
try {
Class serviceClass = Class.forName(service.getClassName());
stopService(new Intent(this, serviceClass));
} catch (ClassNotFoundException e) {}
If you are returning START_REDELIVER_INTENT that might impact you. Here is what the docs say about it:
if this service's process is killed while it is started (after
returning from onStartCommand(Intent, int, int)), then it will be
scheduled for a restart and the last delivered Intent re-delivered to
it again via onStartCommand(Intent, int, int).
But, then again, that says "killed", so it shouldn't impact you.
Other than that, I'm not sure what the problem would be, but if you really can't get it to work and noone else gives you a better answer (which hopefully someone will), you could do registerReceiver(...) in the service, and then in your Activity do sendBroadcast(...), and in the onReceive in the services's receiver, call stopSelf(). I know it's sloppy, and not the best approach, but it's an idea for an alternate method.
Related
I have big problems with stopping a service, which plays audio file. I want to stop the current service before I play another file.
Activity:
public void playTrack(View view){
Intent i=new Intent(this,playService.class);
i.setAction("com.c0dehunterstudios.relaxer.PLAY");
if(isPlaying){
stopService(i);
isPlaying=false;
Log.v("ACTIVITY", "Stopping..");
}
startService(i);
isPlaying=true;
}
Service:
#Override
public void OnDestroy(){
Log.v("SERVICE","Service killed");
player.stop();
super.onDestroy();
}
But sadly it doesn't work - actually it doesn't even come down to the "Service killed" inside OnDestroy().
What am I doing wrong?
First, it's onDestroy, not OnDestroy . Second, you must use the #Override annotation for compile-time checking, so your Service code should look somewhat like this:
#Override
public void onDestroy(){
Log.v("SERVICE","Service killed");
player.stop();
super.onDestroy();
}
First, you need to clarify how many types of services in Android. AFAIK, there are:
Foreground service.
Background service.
Bound service.
Intent service.
These services stop in different ways.
Foreground: only stop when you intentionally stop it by calling stopService() in activity or fragment where you start that service or call stopSelf() in its own service. And Please note only these methods trigger service's onDestroy().
Background: stopService() and stopSelf() do in the same way as foreground. Moreover, you should know this service is in the same thread with activity or fragment calling it, so if you destroy activity or fragment, this service will stop also, but without calling onDestroy(). It basically destroys underground. Thus, if you want to catch when this service stops you need to add android:stopWithTask="false" when declaring service in Manifest file like this:
<application>
//....
<service android:name=".services.catchingStopService"
android:stopWithTask="false" />
//....
</application>
And now in your service class, you can override this method which triggers whenever this service stops:
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
// Your job when the service stops.
}
Bound: you need to handle by your self by bindService() and unbindService(), you will find out it's totally the same as starService() and stopService()
Intent: this type of service stops by itself when it finishes its jobs. And you can use ResultReceiver to communicate between service and activity or fragment. It's similar to BroadcastReceiver. You can search for example on Google easily.
Summary: base on your purpose, pick the type of service satisfying you. And they all agree with:
Don't count on onDestroy() to know when service stops because it
sometimes gets called underground; more accurately, onDestroy calls
when stopService() or stopSelf() calls (BoundService works in the
same way, I think, but by a similar method, maybe unBind(), I did not
test yet).
Use attribute android:stopWithTask="false", instead to know when the
service really stops.
All types of service stop when the device shutdown or OS kills it if
device leaks of memory.
You also should have a look at flag return by onStartCommand() to
be able to deal with when services stop like restart service again or
something. Here are some keyword you can search:
START_STICKY
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
<actionandroid:name="android.intent.action.QUICKBOOT_POWEROFF" />
I had a similar problem even with onDestroy correctly set up - the answer for which could be useful for people coming to this page. For me, onDestroy was not called immediately during stopService, sometimes for a very long time - leaving the service doing work when it should have stopped.
The answer is that this is expected behaviour - I can guess but don't exactly know why. So my solution in this case was to create a public static method to stop the actions of the service manually, which happens at the time it's called, then stopService() will call onDestroy in it's own good time...
In the case for this example (which is probably long gone, I would probably decide to keep the service running until it's expected to quite the app, but provide ways to change audio file, while the service is still active.
In my case I was printing a log inside the onDestroy and It was not printing the log and I thought onDestroy not calling when I call stopService. but in Android studio many times does not print the log so you can once double check or verify with the debug or toast.
I am calling startService() multiple times in my class.
there is a function in my service's onStartCommand(), like this -
Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(StaticValues.TAG, "service started.");
processItem();
return 0;
}
My question is, if I start service again, onStartComamnd() will be called again. So will this call wait till my previous call is over or it will execute both calls to processItem() parallelly?
Edit : Answer I found from links in comments
startService() is asynchronous. So while you are looping the calls, the service itself hasn't gotten any resources and didn't start yet.
The Service will only run in one instance. However, everytime you start the service, the onStartCommand() method is called.
Check : What happens if a Service is started multiple times?
A Service can only be started once, if you want to and love to complicate things use a boolean flag
Using startService() overrides the default service lifetime that is managed by bindService(Intent, ServiceConnection, int): it requires the service to remain running until stopService(Intent) is called, regardless of whether any clients are connected to it. Note that calls to startService() are not nesting: no matter how many times you call startService(), a single call to stopService(Intent) will stop it.
If the service is being started or is already running, the
ComponentName of the actual service that was started is returned; else
if the service does not exist null is returned.
Note that multiple calls to Context.startService() do not nest (though
they do result in multiple corresponding calls to onStartCommand()),
so no matter how many times it is started a service will be stopped
once Context.stopService() or stopSelf() is called;
Link to the Docs
Life Cycle of a Service
My Android application is activating a service that call an 'Activity.
On mainActivity:
startService(new Intent(getBaseContext(),MyService.class));
And then on service:
public int onStartCommand(Intent intent,int flage,int startId){
// Toast.makeText(this, "Yes please", Toast.LENGTH_LONG).show();
Intent mIntent=new Intent(MyService.this,trackingActivity.class);
mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(mIntent);
return START_STICKY; }
At the end of trackingActivity this line is written (Again):
startService(new Intent(getBaseContext(),MyService.class));
That's creates a lot of Services. Is there a better way to create a background service that repeats itself always without creating each time a new Service ?
I tried to do a while loop inside the Activity :
while(true){
Actions on activity
}
But with no success.
Context.startService(Intent) does not create a new Service for each call.
If there is already a matching service running, it passes the intent to that running service, but does not create a new one each time.
See the Android Developer Docs for Context.startService(Intent):
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.
Every call to this method will result in a corresponding call to the target service's onStartCommand(Intent, int, int) method, with the intent given here.
There is similar information in the Android Developer Docs about Starting a Service:
[When starting a service using an intent] the startService() method returns immediately and the Android system
calls the service's onStartCommand() method. If the service is not
already running, the system first calls onCreate(), then calls
onStartCommand().
...
Multiple requests to start the service result in multiple
corresponding calls to the service's onStartCommand(). However, only
one request to stop the service (with stopSelf() or stopService()) is
required to stop it.
I have an android application which starts a service in the main activity with this command:
bindService(new Intent(ctx, MyService.class), _connection, Context.BIND_AUTO_CREATE);
The main activty does excatly nothing with this service (thats why I didnĀ“t provide the code for the Service connection). The idea is that the main activity handels the service lifetime!
It "stops" the service with this code after the user clicks the "close" button of my app:
if (_service != null) {
unbindService(_connection);
}
//Some cleanup here ...
System.exit(0);
I know at this point that no other activity is binded to the service cause every activity is called from the main activity and they unbind from the service at "onStop".
So the problem is that my Service wont call "onDestroy" when the user closes the app!
When I remove the "System.exit(0)" line it will close normally!
How can I make sure that the service is closed properly in this situation?
EDIT:
Ok I read this discussion: Is quitting an application frowned upon?.
Now I rebuild my activities. I have one activity that calls the service with startService, after that it binds the service. When the activity is destroyed it calls unbindService.
The service itself returns START_STICKY in onStartCommand to make it harder to kill it. It calls stopSelf when all work is done.
Now I have the problem that I get the ServiceConnectionLeaked message if the binding still exists! Whats about that? How could I prevent this?
Use finish() instead of System.exit(0)
I am starting a service with a click on a button :
Intent intent = new Intent(getActivity(), UploadService.class);
getActivity().startService(intent);
My apps makes it possible to launch several services.
I know that the first time, onCreate() is called, then if the services is running, onStartCommand() is called.
onStartCommand returns START_STICKY.
But I'm facing a strange behavior :
On the first click, the Service is called, onCreate() then onStartCommand()... etc.
On the second click, while the Service is still running, onStartCommand()... etc.
But when the first is finished, onDestroy() is called, while the second is still in progress... ?
How to avoid that?
Thanks
If you start the Service that is already running then onDestroy() of Service won't be called and the instance of Service already running will be brought to front but if your Service is finished/stopped explicitly then only its onDestroy() will be called.