34

i have a background service on my android APP that is getting my GPS position and sending it to a remote db. It work's fine.

The problem is when i want to stop the service.... it doesn't stops :S. Also no exception or errors on logcat have appeared... it simply doesn't stops.

this is the code to start my srvice (with a button):

startService(new Intent(GPSLoc.this, MyService.class)); //enciendo el service

this is the code where I stop it (on the onactivityresult method):

stopService(new Intent(GPSLoc.this, MyService.class));

I have been debugged the app, and i checked that the stopService codeline has been called every time that i debugged it, but it doesn't stops......

i am sure that it's not stopped cause on my database i still recive gps positions from the emulator when i have press the button to stop the service.

what i am doing bad?

NullPointerException
  • 36,107
  • 79
  • 222
  • 382

11 Answers11

38

Have you implemented onDestroy()? If not, I believe that might be the solution - and you stop your Timer or whatever you're using to run the service within onDestroy().

A service can be stopped by calling its stopSelf() method, or by calling Context.stopService().

See this link for some more information.

Alex Lockwood
  • 83,063
  • 39
  • 206
  • 250
Joakim Berglund
  • 2,859
  • 1
  • 22
  • 30
  • 2
    oh, i am not implementing ondestroy!!!!!! on the service, i am using a thread with a handler, and a simple handler. ¿how to stop them?? – NullPointerException Dec 17 '10 at 15:04
  • 11
    I don't understand why it is necessary to implement onDestroy(). It is just a lifecycle callback method. Can you please clarify? – likejudo Jun 17 '17 at 21:59
  • I have `onDestroy()` implemented, but it is not called after `stopService()`. **Fragment1** - `context?.bindService(Intent(context, AudioService::class.java), serviceConnection, Context.BIND_AUTO_CREATE) context?.startService(Intent(context, AudioService::class.java).apply { putExtra(CONTENT_SELECTED_KEY, uri)})` **Fragment2** - `context?.stopService(Intent(context,AudioService::class.java).apply {putExtra(PLAYER_KEY, STOP.name)})` – AdamHurwitz Jun 07 '19 at 19:03
14

i am sure that it's not stopped cause on my database i still recive gps positions from the emulator when i have press the button to stop the service.

You probably are not unregistering your LocationListener.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
7

I had the same problem. I found that if the service has GoogleApiClient connected and still get location update, the stopService() has totally no effect, the service's industry() was not called. To fix the problem, I created a function to stop the location service in the service code. Call the stopLocationService() from the activity, and then call stopService. Here is the code example:

public class myLocationService extends Service{
...

    public void stopLocationUpdates() {

        LocationService.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,this);       
        mGoogleApiClient.disconnect();

    }
    ...
} 

In activity,

{
    ...
    if(mService != null && isBound) {

        mService.stopLocationUpdates();
        doUnbindService();
        stopService(new Intent(this,   myLocationService.class));

     }
     ...
} 
V-rund Puro-hit
  • 5,518
  • 9
  • 31
  • 50
Hannah Zhang
  • 489
  • 5
  • 5
3

It's very common this situation where I need to stop my service before to finish the process. In some case is not enough with stopService(intent). You should have in mind the onDestroy() implement in my service. Example:

public class MyIntentService extends IntentService {

    // Defines and instantiates an object for handling status updates.
    private BroadcastNotifier mBroadcaster = null;
    private int progress = 0; //THIS IS MY COUNTER FOR EXAMPLE!!!

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {

        progress = 0;
        int tiempo_disponible = intent.getIntExtra("minutos_disponible", 0);

        if (mBroadcaster == null){

            mBroadcaster = new BroadcastNotifier(this);
        }
        // Broadcasts an Intent indicating that processing has started.
        mBroadcaster.broadcastIntentWithState(Constants.STATE_ACTION_STARTED);

        mBroadcaster.broadcastIntentWithState(Constants.STATE_ACTION_RUNNING);

        while (progress < tiempo_disponible) {

            progress++;
            try {
                Log.i(Constants.TAG, "Procesing " + progress);
                mBroadcaster.notifyProgress(progress);
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        // Reports that the feed retrieval is complete.
        mBroadcaster.broadcastIntentWithState(Constants.STATE_ACTION_COMPLETE);
    }

    @Override
    public void onDestroy() {
        progress = 1000000; // WHITH THAT YOU FINISH THE CICLE IF tiempo_disponible NEVER IS MAYOR THAT 1000000, YOU CAN USE OTHER CONDITIONAL!!!!!!
        super.onDestroy();
    }
} 

In this way, when you have stopped the service using stopService method also you will have stopped the process o counter.

public void stopService(){
        context.stopService(intent);
        LocalBroadcastManager.getInstance(context).unregisterReceiver(responseReceiver);
        responseReceiver = null;
        intent = null;
}

Take care! @yaircarreno

yaircarreno
  • 4,002
  • 1
  • 34
  • 32
  • 1
    You are using the wrong Service type. IntentService is designed in order to manage its lifecycle itself. As soon as business logic of the onHandleIntent method is completed - IntentService is destroyed itself and free all associated resources. – Yuriy Chernyshov Dec 11 '14 at 11:32
1

If you are tracking GPS location, you probably used GoogleApiClient.

The concept is that the Service WILL NOT stop,

if an GoogleApiClient instance is still connected within it.

(Or any other issue that need to be destroyed / unregistered first)

So to make it works, implement onDestroy() within your service:

@Override
public void onDestroy()
{
    // Unregistered or disconnect what you need to
    // For example: mGoogleApiClient.disconnect();
    super.onDestroy();
}
David
  • 37,109
  • 32
  • 120
  • 141
  • 1
    i was actually trying to stop a service which uses google api, i forgot to disconnect the api OnDestroy...!! Case Closed.. –  Jun 02 '17 at 07:32
1

I have found the best way to stop a service is to make stop itself. This way you are sure it actually will stop and preserve data integrity. If you want to do it from outside (activity) I usually use a global static attribute.

Per example (Kotlin) if I have MyService, MyActivity and MyObject

My Object

object MyObject{
    abort = false
}

MyService

override fun onHandleIntent(intent: Intent?) {
    startForeground(id,notification)   
    for (i in range){
        if (MyObject.abort) break
        // RUN SOME CODE HERE
    }
    stopForeground(true)
    stopSelf()
}

MyActivity

fun startService() {
    startForegroundService(Intent(this, OptimizationService::class.java))
}
fun stopService() {
    MyObject.abort = true
}
D Dimitrov
  • 115
  • 1
  • 10
0

For those who want to send a request to server periodically, this is my solution. You should have this in your Activity or Fragment Activity

{
private static final Long UPDATE_LOCATION_TIME  = 30 * 60 * 1000l; // 30 minute

private AlarmManager alarm;
private PendingIntent pIntent; 
...

@Override
    protected void onResume() {
        super.onResume();

        // Run background service in order to update users location
        startUserLocationService();

        Log.e(TAG, "onResume");
    }

    @Override
    protected void onStop() {
        super.onStop();

        stopUserLocationService();

        Log.e(TAG, "onStop");
    }

private void startUserLocationService() {
        Log.i(TAG, "Starting service...");
        Intent intent = new Intent(MainFragmentHolder.this, ServiceUserLocation.class);
        pIntent = PendingIntent.getService(this, 0, intent, 0);

        alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
        Calendar cal = Calendar.getInstance();
        alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), UPDATE_LOCATION_TIME, pIntent);
    }

    private void stopUserLocationService() {
        alarm.cancel(pIntent);
        Intent intent = new Intent(MainFragmentHolder.this, ServiceUserLocation.class);
        stopService(intent);
    }

}
Hesam
  • 52,260
  • 74
  • 224
  • 365
0

my problem solved by removing the added views to WindowManager ondestroy

public void onDestroy() {
    isRunning = false;
    super.onDestroy();
    if (checkBox!=null) {
        windowManager.removeView(getlayoutparm(fabsetting,fabrateus,fabexit,true)); 
        windowManager.removeView(checkBox); 
    }
 }
Mosh Feu
  • 28,354
  • 16
  • 88
  • 135
smaznet
  • 196
  • 2
  • 8
0

In my case the stopService is called with startService almost simultaneously so no service is there to be stopped. Try delay stopService for a few seconds. :)

He Yifei 何一非
  • 2,592
  • 4
  • 38
  • 69
0

@Override

public void onDestroy() {

    Log.d(TAG, "onDestroy");
    super.onDestroy();
    if (mLocationManager != null) {

        for (int i = 0; i < mLocationListeners.length; i++) {

            try {

                mLocationManager.removeUpdates(mLocationListeners[i]);

            } catch (Exception ex) {

                Log.d(TAG, "fail to remove location listners, ignore", ex);

            }

        }

    }

}
Ashwin H
  • 695
  • 7
  • 24
0

it could be perhaps that you are creating a new Intent everytime you call the stop service.

stopService(new Intent(GPSLoc.this, MyService.class));

perhaps try :

Intent intnet = new Intent(GPSLoc.this, MyService.class); // create el service

startService(intenet); 
stopService(intent);
Stelios Philippou
  • 103
  • 1
  • 3
  • 13