Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: stopService doesn't call onDestroy

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?

like image 781
c0dehunter Avatar asked Jan 31 '12 20:01

c0dehunter


People also ask

Is onDestroy guaranteed to be called?

Android Activity onDestroy() is not always called and if called only part of the code is executed. Bookmark this question. Show activity on this post. onDestroy() is not always called.

How do you call onDestroy?

This example demonstrates about How do I call OnDestroy Activity in Android app. Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main.

Does activity finish call onDestroy?

Third, finish() does not call onDestroy() . You can tell that by reading the source code.

When onDestroy method is called in Android?

If onDestroy() is called as the result of a configuration change, the system immediately creates a new activity instance and then calls onCreate( ) on that new instance in the new configuration.


2 Answers

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();  
}
like image 157
Mayjak Avatar answered Sep 17 '22 16:09

Mayjak


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" />
like image 20
Nguyen Tan Dat Avatar answered Sep 20 '22 16:09

Nguyen Tan Dat