我的应用程序中有一项服务,可用于向服务器发送请求。在我发送请求开始服务器上的操作后,我需要通过每 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/