Android - Kill Bound Activity on Service Destroy - android

I have an activity that has:
#Override
protected void onStart() {
super.onStart();
// Bind to LocalService
exampleService = new Intent(this, exampleService.class);
bindService(exampleService, mConnection, Context.BIND_AUTO_CREATE);
startService(exampleService);
}
Now If I go to Manage Applications and check running services and kill the service, the activity is still running as a background process.
How can I have it so the activity that is bound to the service is killed also on destroy?

This is happening because in android when you start a service then you need to manually stop that service before you kill bound any activity. So try to stop that service inside onStop() or Onpause() method.
Visit this http://androidtutorial4u.blogspot.in/p/forum.html
We have started new forum in which you can ask your questions regarding android as well as answer the questions.

Related

Unable to start service in background

I have a service that I use for listening to a socket service. I only need this service to be running whilst the app is in the foreground. However, in production I am seeing several crashes:
IllegalStateException
Not allowed to start service Intent { cmp=com.app.app/.app.sockets.EventHandlingService }: app is in background
Initially, I was calling this in the onCreate of my Activity, and according to some other SO questions, technically the app isn't foregrounded then. So I moved it into the onResume, and yet I still see it happening. This is how it is started:
#Override
protected void onResume() {
super.onResume();
Intent serviceIntent = new Intent(this, EventHandlingService.class);
startService(serviceIntent);
bindService(serviceIntent, serviceConnection, 0);
}
I am unable to reproduce this crash locally.

Service notification when an activity is killed

My application has an activity and a service running in the same process. When the user terminates the activity by clicking the STOP button, the activity causes the service to terminate.
From the Android documentation I understand that the system can kill a process to reclaim resources:
"Once your activity is stopped, the system might destroy the instance if it needs to recover system memory. In extreme cases, the system might simply kill your app process without calling the activity's final onDestroy() callback, ..."
Question 1: Is it possible for my activity to be killed but not the service? I would prefer my service remain alive.
If the answer is 'yes' then
Question 2: Is there a mechanism where the service can be notified that the activity has been killed?
IBinder.linkToDeath has the functionality I need but seems to apply to a process, not an activity.
I've thought of an indirect method like having the activity take ownership of semaphore and having the service use a thread to wait on it. Then when the activity gets killed it will release the semaphore and the service will get it, providing the notification. But I was wondering if there wasn't an android-centric technique I could use.
[begin edit]
After reading the very helpful comments you've provided I'd like to clarify the scenario I'm presenting.
I've started two components: an activity and a service. The application is configured so that service can continue to run after the activity has stopped and been destroyed. The user can restart/start the activity multiple times and it will use the same instance of the service.
Normally the activity will notify the service it has been destroyed during onDestroy(). But onDestroy() may not be called.
I'd like to know whether there is some android-specific mechanism I can use to notify the service that the activity has been killed without the call to its onDestroy() method having been made.
[end edit]
Thanks for your help.
Will
As I said before, single activity won't be killed by android without calling onDestroy(). If Android needs more memory it kills whole process(with all activities and services). Here is description, documentation is wrong about this.
Service can be also created in other process but it has to be set int the manifest. And then you can use iBinder to get notification when process(with all activities) is killed by Android
Yes services and activities can run independently of each other.
To achieve what you're trying to do I would explicitly start your service using startService() in your activity's onStart() function (or wherever you wish to launch it) and also bind to it at the same point. Binding without an explicit startService will cause the service to stop when you kill the activity (unless some other activity is still bound to it).
In your activity's onStop() call a function on your service to tell it the activity has been killed.
In your Activity:
private ServiceRecordJourney yourService;
private ServiceConnection serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
YourServiceBinder binder = (YourServiceBinder) service;
yourService= binder.getService();
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
}
};
#Override
public void onStart(){
super.onStart();
startService(new Intent(this, YourService.class));
// Bind to Service
Intent intent= new Intent(this, YourService.class);
bindService(intent, serviceConnection , Context.BIND_AUTO_CREATE);
}
#Override
public void onStop(){
super.onStop();
if(yourService != null){
yourService.activityKilledFunction();
unbindService(serviceConnection);
}
}
Your service will need to be foreground (and display a notification) to further stop it from being killed off by the OS. Also as it's been explicitly started you will need to handle an explicit stop on the service (either call stopSelf() on the service or stopService() in a context object.
You can handle communication to the service using multiple startService() calls with different intents but I prefer the above approach (and I'm sure that in the case binding is the preferable approach).
Also whilst the service is running the activity will bind and unbind to the service each time the activity is started or stopped by the user.

How to stop a Service from running after user stops viewing applications Activities. Android

I have the following code in each of the 5 activities of my app. I wanted to keep the service running that is bound to these five activities. It will play music in the background. However when the user navigates away from the any of these five activities the Service should be killed. Using the code below I am able to get it so that the music plays in the background when navigating between the activities. but the Service keeps running after leaving the application. What is the best way to solve this problem? How about some creative ideas.
I put this Toast message in the onDestroy method of the service so I can tell when the service is stopped.
Toast.makeText(this, "My Service Destroyed", Toast.LENGTH_LONG).show();
I never see any Toast message pop up when I leave the application. The other toast messages do show to indicate that the service has started.
#Override
public void onPause() {
super.onPause();
unbindService(serviceConnection);
}
#Override
public void onResume() {
//After a pause OR at startup
super.onResume();
//add this to the onResume of the activity
// startService(new Intent(this, AudioService.class));
bindService(new Intent(this, AudioService.class),
serviceConnection, Context.BIND_AUTO_CREATE);
}
According to the documentation here:
Multiple clients can bind to the service at once. When a client is done interacting with the service, it calls unbindService() to unbind. Once there are no clients bound to the service, the system destroys the service.
So maybe you're missing some unbind in one of your activities. You can check this by printing a log in the onBind and onUnbind methods of your service.

Android bound service - should I manually reconnect in onServiceDisconnected or it tries reconnect automatically?

If i get disconnected from bound service due to some unexpected circumstances, after i called, should I manually reconnect in onServiceDisconnected or it tries to reconnect automatically?
public class MyServiceConnection extends Activity implements ServiceConnection {
MyBinder binder;
#Override
protected void onStart() {
super.onStart();
connect();
}
private void connect() {
bindService(new Intent(this, MyService.class),
this, Service.BIND_AUTO_CREATE);
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
binder = (MyBinder) service;
}
#Override
public void onServiceDisconnected(ComponentName name) {
binder = null;
//should i reconnect here ?
connect();
}
}
According to the ServiceConnection API:
public abstract void onServiceDisconnected (ComponentName name)
Called when a connection to the Service has been lost. This typically happens when the process hosting the service has crashed or been killed. This does not remove the ServiceConnection itself -- this binding to the service will remain active, and you will receive a call to onServiceConnected(ComponentName, IBinder) when the Service is next running.
Back to your question:
#Override
public void onServiceDisconnected(ComponentName name) {
binder = null;
//should i reconnect here ?
connect();
}
It is all depend on which process the actual service lives.
Local Service:
Service is running in the same process as other components (i.e. activity that bound to it) from the same application, when this single application-scoped process has crashed or been killed, it is very likely that all components in this process (include the activity that bound to this service) are also destroyed. In this case, calling connect() inside onServiceDisconnected() doesn't make any effect, as when application process is recovered, everything is rolling over from very beginning and the activity is recreated again and service is bound in activity's onStart() callback.
Remote Service:
Service is running in separate process, when this process has crashed or been killed, only the actual service is destroyed, the activity lives in another process that bound to the service is remained, so it is probably OK to call connect() in its onServiceDisconnected() callback in order to re-create/re-bind the service.
Check out here to see how to configure service running on separate process in AndroidManifest.xml.
Bumped into this old question when making a research for a blog post. The accepted answer is quite good, but does not show the entire picture when it comes to bound IPC (remote) services.
State diagram of a connection to bound IPC service looks like this:
And the answer to OP's question is: it depends.
First of all - when service crashes or being killed by OS it remains bound. So the question becomes whether the system will re-create the service or not...
In case bound IPC service is being killed by OS, it will be re-created and you'll get a call to onServiceConnected(), therefore no need to "reconnect".
In case bound IPC service crashes, the system will attempt to re-create it once - if it crashes for the second time the system will not re-create it again (tested on JellyBean, Lollipop and Marshmallow).
Theoretically, you could unbindService() and then bindService() on each call to onServiceDisconnected() - this should work (I think).
However, writing a really reliable client for bound IPC service is a bit more work, and the general idea (alongside tutorial app) could be found here.

Android: How to Stop service that is started by bindService() with BIND_AUTO_CREATE option?

I start service by using:
private ServiceConnection _serviceConnection = new ServiceConnection() {...}
bindService(new Intent(this, MainService.class), _serviceConnection, Context.BIND_AUTO_CREATE);
I want to 'restart' the service. (Let's not argue why I want to do that)
I do that by:
unbindService(_serviceConnection);
// Do some initialization on service
bindService(new Intent(this, MainService.class), _serviceConnection, Context.BIND_AUTO_CREATE);
I noticed service doesn't die(onDestroy doesn't run) until I call next bindService();
So some static initialization I did on service got cleared by onDestroy() implementation.
Question: How do you make sure unbindService() will stop service (run onDestory()),
so that I could do initialization after and re-run bindService()?
Android keeps services around at it's own discretion, even after calling unbindService or stopService.
If you need to immediately reinitialize some data on the service side, you most likely need to provide a service method for doing that.
Question: How do you make sure unbindService() will stop service (run onDestory()), so that I could do initialization after and re-run bindService()?
The timing of onDestroy() after the last unbindService() is indeterminate and certainly asynchronous. You could also try calling stopService() yourself, but that too is asynchronous, so you don't know when it will be stopped.
I do not know of a reliable way for you to "restart" a service using the binding pattern.
You can use onRebind() if you return true in onUnbind().
see here:
http://developer.android.com/guide/components/bound-services.html

Categories

Resources