Android 服务在 Runnable 仍在执行时关闭

标签 android multithreading service broadcastreceiver android-broadcastreceiver

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

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

最佳答案

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

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

关于Android 服务在 Runnable 仍在执行时关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40759849/

相关文章:

android - 使用 Realm Mobile Platform 在应用程序用户之间共享数据

java - 返回的位置在 TomTom Android SDK 中为空

MySQL 服务不再启动

python - TensorFlow 服务与 TensorFlow 服务

java - 如何在EditText中针对不同的输入长度显示不同的消息?

android - Xamarin ARcore 改变 3D 对象的位置

python - 检测 OS X 中挂起的 python shell

java - 在 ConcurrentHashMap 中存储复杂对象

c - pthread_cond_wait() 同时唤醒两个线程

windows - C# - 服务如何设置启动参数