bulubuloa
bulubuloa

Reputation: 597

StopService onDestroy being called but service not ending

I try using TimerTask to download data from the server api, the task loops in background app.

I have a service class:

public class RequestNewInvoice extends Service {

    private Timer timer;
    private CheckTask checkTask;
    private Handler handler;
    private JSONParser jsonParser;
    private JSONObject jsonObject;   
    private boolean startService = true;

    private void init(){     
        this.handler = new Handler(new Handler.Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                Log.e("Message: ",msg.obj+"");
                return false;
            }
        });

        this.timer = new Timer();
        this.checkTask = new CheckTask();
        this.startService = true;
        timer.scheduleAtFixedRate(checkTask, 5000, 20 * 1000);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(final Intent intent, int flags, final int startId) {
        init();
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e("SERVICE STOP", "true");
        startService = false;
        checkTask.cancel();
        timer.cancel();
        timer.purge();
    }

    private class CheckTask extends TimerTask{
        @Override
        public void run() {
            funcCheckInvoice();
        }
    }

    public void funcCheckInvoice(){
        try{
            if(startService){            
               Log.e("SERVICE START", "true");
               HttpParams httpParameters = new BasicHttpParams();
               HttpConnectionParams.setConnectionTimeout(httpParameters, SuperVAR.GET_CURRENT_SHIPMENT_TIMEOUT);
                HttpConnectionParams.setSoTimeout(httpParameters, SuperVAR.GET_CURRENT_SHIPMENT_TIMEOUT);

                httpClient = new DefaultHttpClient(httpParameters);
                HttpGet httpGet = new HttpGet(SuperVAR.URL_GET_LIST_INVOICE_IN_CURRENT_SHIPMENT+"?"+ URLEncodedUtils.format(_REQUEST, "utf-8")+"unused="+System.currentTimeMillis()/1000);

                httpGet.setHeader("token",token);
                httpGet.setHeader("Cache-Control","no-cache");
                httpGet.setHeader("Cache-Control","no-store");

                HttpResponse httpResponse = httpClient.execute(httpGet);
                HttpEntity httpEntity = httpResponse.getEntity();
                jsonObject = jsonParser.getJSONFromRESPONSE(httpEntity);


                if(jsonObject == null){
                        Message message = Message.obtain();
                        message.obj = "get null.... internet like shit T_T";
                        handler.sendMessage(message);
                }else {
                        Message message = Message.obtain();
                        message.obj = "download ok";
                        handler.sendMessage(message);
                }
            }else {
                Log.e("SERVICE START", "false");
                return;
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    } 
}

When I run stopService in Activity Class, service calls the onDestroy function, but Timer still lives on.

How can I destroy the timer task?

Upvotes: 2

Views: 2201

Answers (2)

Peyman Assadi
Peyman Assadi

Reputation: 48

Use Handler and on destroy remove callback task

    TimerTask scanTask;
    final Handler handler = new Handler();
    Timer t = new Timer();

    scanTask = new TimerTask() {
        public void run() {
            handler.post(task);
        }};
    t.schedule(scanTask,  5000, 20 * 1000);

    Runnable task = new Runnable() {
    @Override
    public void run() {
            //START YOUR JOB
            (new FetchData()).execute();

    }
};





@Override
public void onDestroy() {
    super.onDestroy();
    Log.e("SERVICE STOP", "true");
    startService = false;
    checkTask.cancel();
    timer.cancel();
    timer.purge();
    handler.removeCallbacks(task);

}

public class FetchData extends AsyncTask<Void, Void, Void>
{
    @Override
    protected Void doInBackground(Void... params)
    {
           funcCheckInvoice();
    }
}

Upvotes: 1

Christian Abella
Christian Abella

Reputation: 5797

You have started your Service as START_STICKY which could be the reason why you can't stop the service.

Below is the definition of START_STICKY.

Constant to return from onStartCommand(Intent, int, int): if this service's process is killed while it is started (after returning from onStartCommand(Intent, int, int)), then leave it in the started state but don't retain this delivered intent. Later the system will try to re-create the service. Because it is in the started state, it will guarantee to call onStartCommand(Intent, int, int) after creating the new service instance; if there are not any pending start commands to be delivered to the service, it will be called with a null intent object, so you must take care to check for this.

This mode makes sense for things that will be explicitly started and stopped to run for arbitrary periods of time, such as a service performing background music playback.

Try using START_NOT_STICKY

You also need to change the way you are calling cancel as you are calling scheduleAtFixedRate.

private ScheduledThreadPoolExecutor scheduleTaskExecutor;
private ScheduledFuture schedule;
...
scheduleTaskExecutor = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(5);
schedule =  scheduleTaskExecutor.scheduleAtFixedRate(checkTask, 5000, 20 * 1000);


@Override
public void onDestroy() 
{
  super.onDestroy();
  startService = false;
  checkTask.cancel();

  schedule.cancel(true);

}

Upvotes: 0

Related Questions