Служба Android отключается, пока Runnable все еще выполняется

У меня есть служба в моем приложении, с помощью которой я отправляю запросы на сервер. После того, как я отправлю запрос на запуск операции на сервере, мне нужно опрашивать сервер на наличие обновлений, отправляя запрос каждые 15 секунд для отслеживания прогресса. Для этого я использую ScheduledExecutorService, который вызывает Runnable.

Служба делает кучу вещей в onHandleIntent, а затем запускает ScheduledExecutorService, который выполняет опрос. Все это работает нормально.

Проблема заключается в том, что когда ScheduledExecutorService через определенные промежутки времени выполняет Runnable, служба уничтожается, так как вызывается метод onDestroy. Есть ли способ предотвратить это?

У меня есть широковещательный приемник, зарегистрированный в службе, который может быть запущен пользователем в любое время, пока ScheduledExecutorService выполняет Runnable. Но поскольку Служба уничтожена, Получатель отменяет регистрацию.

Вот некоторый упрощенный код:

@Override
protected void onHandleIntent(Intent intent) {
    Log.d(TAG, "OnHandleIntent started");

    try {

        if (intent != null) {
            final String action = intent.getAction();

            if (getActionUpload().equals(action)) {

                wakeLock.acquire();
                notificationConfig = new CustomNotificationConfig();

                //Register receiver to stop operation
                IntentFilter filter = new IntentFilter(ThirdPartyStopReceiver.ACTION_STOP);
                filter.addCategory(Intent.CATEGORY_DEFAULT);
                mThirdPartyStopReceiver = new ThirdPartyStopReceiver();
                registerReceiver(mThirdPartyStopReceiver, filter);

                Boolean operationStarted = startOperation();

                if (operationStarted) {
                    checkProgressAtIntervals();
                }
            }
        }

    } catch (Exception e) {
        Log.e(TAG, "Error with XML");
        e.printStackTrace();
    } finally {
        wakeLock.release();
    }
}


@Override
public void onDestroy() {
    super.onDestroy();
    Log.d(TAG, "onDestroy");
    try {
        //Unregister the receiver
        unregisterReceiver(mThirdPartyStopReceiver);
    } catch (IllegalArgumentException e) {
        //Receiver has already been unregistered. Do nothing
        e.printStackTrace();
    }
}

private void checkProgressAtIntervals() {
    Log.d(TAG,"in checkProgressAtIntervals");

    final ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();

    ses.scheduleAtFixedRate(new Runnable() {
        @Override
        public void run() {
            try {
                int progress = sendProgressRequest();

                if(isCanceled){
                    sendCancelRequest();
                    ses.shutdown(); //Stop polling
                }

                if (progress >= 100) {
                    ses.shutdown(); //Stop polling
                }

            } catch (Exception e) {
                Log.e(TAG, "Exception in sendProgressRequest ");
                e.printStackTrace();
            }
        }
    }, 1, 15, TimeUnit.SECONDS);

}

public class ThirdPartyStopReceiver extends BroadcastReceiver {

    public static final String ACTION_STOP = "thirdpartystop";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "Cancel request received in onReceive");
        isCanceled = true;

        //...

    }
}

Итак, как видите, мне нужно выполнить некоторый код в службе, если получена широковещательная рассылка «Стоп».

Я пытался использовать обработчик с его методом postDelayed, но служба уничтожается до того, как обработчик начинает выполняться, поэтому Runnable никогда не выполняется. Я попытался создать обработчик с помощью Looper.myLooper(), но с тем же результатом. Поскольку runnable содержит вызовы HTTP, создание экземпляра Handler с Looper.getMainLooper() вызывает NetworkOnMainThreadException


person ForeverNoob    schedule 23.11.2016    source источник
comment
Вы можете использовать службу переднего плана, вот справочная ссылка developer.android.com/guide /components/services.html#Foreground   -  person Samuel Robert    schedule 23.11.2016


Ответы (1)


Похоже, вы используете метод IntentService, который останавливается после окончания своей работы, то есть метод onHandleIntent. IntentService предназначен для недолгого использования.

Попробуйте вместо этого использовать обычный Service. Имейте в виду, что Android может остановить службу по своему усмотрению, но в целом служба будет работать в течение длительного периода времени.

person nandsito    schedule 23.11.2016
comment
Это сработало! Я переместил код с onHandleIntent на onStart и изменил свой класс на расширение Service вместо IntentService. - person ForeverNoob; 23.11.2016