Android Runnable 仍在执行时服务关闭

Android Service shuts down while Runnable is still executing

我的应用程序中有一项服务,可用于向服务器发送请求。在我发送请求开始服务器上的操作后,我需要通过每 15 秒发送一个请求来轮询服务器以获取更新以跟踪进度。为此,我使用调用 Runnable 的 ScheduledExecutorService。

该服务在 onHandleIntent 中做了很多事情,然后启动执行轮询的 ScheduledExecutorService。所有这些都工作正常。

问题是当 ScheduledExecutorService 每隔一段时间执行 Runnable 时,服务被销毁,因为调用了 onDestroy 方法。有什么办法可以防止这种情况发生吗?

我在服务中注册了一个广播接收器,用户可以在 ScheduledExecutorService 执行 Runnable 时随时触发它。 但是由于 Service 被销毁,Receiver 被取消注册。

这里是一些简化的代码:

@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;

        //...

    }
}

如您所见,如果收到 "Stop" 广播,我需要在服务中执行一些代码。

我曾尝试使用具有 postDelayed 方法的 Handler,但服务在 Handler 开始执行之前被销毁,因此 Runnable 永远不会执行。我尝试用 Looper.myLooper() 实例化处理程序,但结果相同。 由于 runnable 包含 HTTP 调用,因此使用 Looper.getMainLooper() 实例化处理程序会抛出 NetworkOnMainThreadException

您似乎在使用IntentService,它在结束工作后停止,即onHandleIntent 方法。 IntentService 是短暂的。

请尝试使用常规 Service。请注意,Android 可以自行决定停止服务,但一般来说,服务会 运行 很长一段时间。