Search code examples
androidkotlinandroid-workmanager

PeriodicWorkRequest status stuck at Enqueued


I'm working on an Android App to send out notifications when a date stored in a local database is reached. To do this, I'm attempting to use a periodic work request that will call a function to compare the stored date to the current date and notify the user if the date has been reached. However, when checking Background Task Inspector, my Worker is permanently in "Enqueued" status and never runs this function and I'm unsure why.

Creating the work request in MainActivity.kt's OnCreate() method:

class MainActivity : ComponentActivity() {
    @RequiresApi(Build.VERSION_CODES.O)
    override fun onCreate(savedInstanceState: Bundle?) {
        
    //...

        //For WorkManager to manage Notifications
        // Create periodic work request
        val periodicWorkRequest = PeriodicWorkRequestBuilder<EventCheckWorker>(5, TimeUnit.SECONDS) //Temporarily set to 5 sec. for testing
            .build()

        // Enqueue periodic work
        WorkManager.getInstance(this).enqueueUniquePeriodicWork(
            "EventCheckWorker",
            ExistingPeriodicWorkPolicy.KEEP,
            periodicWorkRequest
        )

    }
}

And EventCheckWorker to check if date has been reached:

class EventCheckWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
    override fun doWork(): Result {
        Log.d("START doWork", "START doWork")
        return try {
            // Retrieve all events from Assignment
            val assignmentsFlow = AssignmentDatabase.getDatabase(applicationContext).assignmentDao()
                .getAllAssignments()

            val today = Calendar.getInstance().timeInMillis

            runBlocking {
                //Converts Flow<List<Assignment>> into List<Assignment>
                assignmentsFlow.collect { assignments ->
                    // Check if any event date is today. If today, send a notification
                    for (assignment in assignments) {
                        Log.d("Loop doWork", "Loop doWork " + assignment.id.toString())
                        if (assignment.dueDate.time <= today) {
                            sendNotification(applicationContext, assignment.name)
                        }
                    }
                }
            }

            Log.d("SUCCESS doWork", "SUCCESS doWork")
            Result.success()
        } catch (e: Exception) {
            // Log the exception
            Log.e("EventCheckWorker", "Error processing events", e)
            Result.failure()
        }
    }
}

The Log statements inside EventCheckWorker never appear in Logcat, meaning doWork() is never called. I'm not sure what could be stopping this method from running.

Here's a view of the Inspector. I see that I have a constraint requiring a network connection and I'm also unsure why that's there, as I removed the code setting that constraint and re-ran the app. Regardless though, my emulated device is connected to a network so I'd assume this shouldn't be an issue.

Background Task Inspector output

I'd also tried waiting the minimum interval of 15 minutes for the periodic request to occur, and again, the function did not run.

Any help with this would be greatly appreciated. Thank you.


Solution

  • "Temporarily set to 5 sec. for testing" will be ignored, the minimum Period Work Request period is 15 minutes.

    https://android.googlesource.com/platform/frameworks/support/+/androidx-1.0-dev/work/workmanager/src/main/java/androidx/work/PeriodicWorkRequest.java#34

    and from the docs

    Periodic work has a minimum interval of 15 minutes.

    So you are probably missing the first immediate running of the request and not waiting enough time for the next request as the lifecycle goes:-

    The normal lifecycle of a PeriodicWorkRequest is ENQUEUED -> RUNNING -> ENQUEUED

    Or as you specify "ExistingPeriodicWorkPolicy.KEEP" as you might already have an instance queued so a new one won't be added use CANCEL_AND_REENQUEUE or UPDATE instead.