How can I check if WorkManager
is scheduled already.
Here is my code that schedule WorkManager
.
public static void scheduleWork() {
PeriodicWorkRequest.Builder photoCheckBuilder =
new PeriodicWorkRequest.Builder(WorkManagerService.class, TIME_INTERVAL_IN_SECONDS,
TimeUnit.SECONDS);
PeriodicWorkRequest photoCheckWork = photoCheckBuilder.build();
WorkManager instance = WorkManager.getInstance();
if (instance != null) {
instance.enqueueUniquePeriodicWork("TAG", ExistingPeriodicWorkPolicy.KEEP , photoCheckWork);
}
}
I call scheduleWork()
in onCreate()
of my Application
class.
Even I can check my service is running or not by this method. But I don't want schedule WorkManager if it is already scheduled to remove inconsistency in scheduled time.
Like
if(!workManagerIsScheduled())
{
scheduleWork();
}
Any solutions?
Update
If you need to check already running work manager just because you don't want duplicate works. You can simply use enqueueUniquePeriodicWork()
This method allows you to enqueue a uniquely-named
PeriodicWorkRequest, where only one PeriodicWorkRequest of a
particular name can be active at a time. For example, you may only
want one sync operation to be active. If there is one pending, you can
choose to let it run or replace it with your new work.
So you don't need to worry about duplicacy about works.
workmanager.enqueueUniquePeriodicWork(TAG, ExistingPeriodicWorkPolicy.KEEP , photoCheckWork);
- Where TAG is unique name by which work manager will check duplicacy.
- You can choose between
ExistingPeriodicWorkPolicy.KEEP
and ExistingPeriodicWorkPolicy.REPLACE
.
Orignal Post
I created this method when I did not find any.
Check if work is running by TAG
if (your_work_manager.version >= 1.0.0-alpha11)
private boolean isWorkScheduled(String tag) {
WorkManager instance = WorkManager.getInstance();
ListenableFuture<List<WorkInfo>> statuses = instance.getWorkInfosByTag(tag);
try {
boolean running = false;
List<WorkInfo> workInfoList = statuses.get();
for (WorkInfo workInfo : workInfoList) {
WorkInfo.State state = workInfo.getState();
running = state == WorkInfo.State.RUNNING | state == WorkInfo.State.ENQUEUED;
}
return running;
} catch (ExecutionException e) {
e.printStackTrace();
return false;
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
}
if (your_work_manager.version < 1.0.0-alpha11)
private boolean isWorkScheduled(String tag) {
WorkManager instance = WorkManager.getInstance();
LiveData<List<WorkStatus>> statuses = instance.getStatusesByTag(tag);
if (statuses.getValue() == null) return false;
boolean running = false;
for (WorkStatus workStatus : statuses.getValue()) {
running = workStatus.getState() == State.RUNNING | workStatus.getState() == State.ENQUEUED;
}
return running;
}
It will return true
when some of its task is RUNNING
or ENQUEUED
.
Sample code
public static final String TAG_MY_WORK = "mywork";
if(!isWorkScheduled(TAG_MY_WORK)) { // check if your work is not already scheduled
scheduleWork(TAG_MY_WORK); // schedule your work
}
public static void scheduleWork(String tag) {
PeriodicWorkRequest.Builder photoCheckBuilder =
new PeriodicWorkRequest.Builder(WorkManagerService.class, TIME_INTERVAL_IN_SECONDS,
TimeUnit.SECONDS);
PeriodicWorkRequest photoCheckWork = photoCheckBuilder.build();
WorkManager instance = WorkManager.getInstance();
instance.enqueueUniquePeriodicWork(tag, ExistingPeriodicWorkPolicy.KEEP , photoCheckWork);
}
from 1.0.0-alpha11 along with many things WorkStatus will not work it's removed and it's a breaking change. Check Release Notes
WorkStatus has been renamed to WorkInfo. All corresponding getStatus method variants have been renamed to the corresponding getWorkInfo variants. This is a breaking change.
after updating to alpha11 the working code is.
private boolean isWorkScheduled(List<WorkInfo> workInfos) {
boolean running = false;
if (workInfos == null || workInfos.size() == 0) return false;
for (WorkInfo workStatus : workInfos) {
running = workStatus.getState() == WorkInfo.State.RUNNING | workStatus.getState() == WorkInfo.State.ENQUEUED;
}
return running;
}
Since October 11 (2018) you can use ListenableFuture instead of SynchronousWorkManager which was removed:
You can now synchronously get and observe by using ListenableFutures. For example, WorkManager.enqueue() used to return void; it now returns a ListenableFuture. You can call ListenableFuture.addListener(Runnable, Executor) or ListenableFuture.get() to run code once the operation is complete.
More info can be found here.
Another option can be using ListenableWorker:
A class that can perform work asynchronously in WorkManager. For most cases, we recommend using Worker, which offers a simple synchronous API that is executed on a pre-specified background thread.
It returns ListenableFuture after you call startWork() function.
More info can be found here.
If you are using Kotlin you can write an extension function like this
fun WorkManager.isAnyWorkScheduled(tag: String): Boolean {
return try {
getWorkInfosByTag(tag).get().firstOrNull { !it.state.isFinished } != null
} catch (e: Exception) {
when (e) {
is ExecutionException, is InterruptedException -> {
e.printStackTrace()
}
else -> throw e
}
false
}
}
I found the answer in this post and I made some editing.
In my project; i'm sending location info to server every 15 minutes. And i dont want to schedule WorkManager if it is already scheduled.
// Fırst I'm creating workRequest here.
private void createWorkRequest() {
Constraints constraints = new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build();
PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest.Builder
(LocationWorker.class, 15, TimeUnit.MINUTES)
.setConstraints(constraints)
.build();
WorkManager.getInstance(this)
.enqueueUniquePeriodicWork("sendLocation", ExistingPeriodicWorkPolicy.REPLACE, periodicWorkRequest);
}
// Then i'm learning the state of Work
private WorkInfo.State getStateOfWork() {
try {
if (WorkManager.getInstance(this).getWorkInfosForUniqueWork("sendLocation").get().size() > 0) {
return WorkManager.getInstance(this).getWorkInfosForUniqueWork("sendLocation")
.get().get(0).getState();
// this can return WorkInfo.State.ENQUEUED or WorkInfo.State.RUNNING
// you can check all of them in WorkInfo class.
} else {
return WorkInfo.State.CANCELLED;
}
} catch (ExecutionException e) {
e.printStackTrace();
return WorkInfo.State.CANCELLED;
} catch (InterruptedException e) {
e.printStackTrace();
return WorkInfo.State.CANCELLED;
}
}
// If work not ( ENQUEUED and RUNNING ) i'm running the work.
// You can check with other ways. It's up to you.
private void startServerWork() {
if (getStateOfWork() != WorkInfo.State.ENQUEUED && getStateOfWork() != WorkInfo.State.RUNNING) {
createWorkRequest();
Log.wtf("startLocationUpdates", ": server started");
} else {
Log.wtf("startLocationUpdates", ": server already working");
}
}