当Runnable仍在执行时,Android服务将关闭

时间:2016-11-23 08:56:31

标签: 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;

        //...

    }
}

正如您所看到的,如果收到“停止”广播,我需要在服务中执行一些代码。

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

1 个答案:

答案 0 :(得分:1)

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

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