У меня есть служба в моем приложении, с помощью которой я отправляю запросы на сервер. После того, как я отправлю запрос на запуск операции на сервере, мне нужно опрашивать сервер на наличие обновлений, отправляя запрос каждые 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