Skip to content

Conversation

@seadowg
Copy link
Member

@seadowg seadowg commented Sep 21, 2025

This should fix a problem (pointed out by @lognaturel on Slack) where error notifications are not being shown after manually refreshing a project from the "Start new form" screen.

Why is this the best possible solution? Were any other approaches considered?

Comments inline.

Also: the 3 changes here aren't tested - initially this was just because I wasn't confident about how to fix so was relying on manual testing between myself and QA to get things right. When then trying to write tests, I discovered we're going to need to rework things - our current TaskSpecWorkerTest crashes if setForegroundAsync is called and our TestScheduler is not set up to test real foreground service behaviour. I'll follow up with a PR that adds coverage for all three changes here.

How does this change affect users? Describe intentional changes to behavior and behavior that could have accidentally been affected by code changes. In other words, what are the regression risks?

The only thing affected here is that notifications should be shown for errors that happen when manually refreshing.

Before submitting this PR, please make sure you have:

  • added or modified tests for any new or changed behavior
  • run ./gradlew connectedAndroidTest (or ./gradlew testLab) and confirmed all checks still pass
  • added a comment above any new strings describing it for translators
  • added any new strings with date formatting to DateFormatsTest
  • verified that any code or assets from external sources are properly credited in comments and/or in the about file.
  • verified that any new UI elements use theme colors. UI Components Style guidelines

@seadowg seadowg added needs testing high priority Should be looked at before other PRs/issues labels Sep 21, 2025
@seadowg seadowg changed the base branch from master to v2025.3.x September 21, 2025 16:18
@dbemke
Copy link

dbemke commented Sep 22, 2025

To keep track of steps to reproduce and the expected behavior:

Steps to reproduce:

  1. Create a draft of a form in Central.
  2. Click "try on device" and scan the QR code in Collect.
  3. After download the project(draft form) in Collect, go to Central and delete the form.
  4. Go to Collect to "Start new form" and tap the arrow icon.

Expected behavior
The arrow (in "Start new form") changes to arrow+exclamation mark and there's the notification "Form update failed" Show details.
After tapping show details the user sees information about the [Drafts] and form "Collect can't reach the server...."

@seadowg Please verify if the step to reproduce and expected behavior are ok.

@dbemke
Copy link

dbemke commented Sep 22, 2025

If the steps to reproduce and the expected behavior described above are ok, then the notifications isn't shown in this case on Android 10 and 16.

@seadowg
Copy link
Member Author

seadowg commented Sep 22, 2025

@seadowg Please verify if the step to reproduce and expected behavior are ok.

That looks right to me. That's consistent with Collect v2025.2.3 right?

If the steps to reproduce and the expected behavior described above are ok, then the notifications isn't shown in this case on Android 10 and 16.

In this PR? I'll have a look.

@dbemke
Copy link

dbemke commented Sep 22, 2025

In this PR? I'll have a look.

Yes in the PR

@seadowg
Copy link
Member Author

seadowg commented Sep 22, 2025

@dbemke yeah looks like there's a second bug, to fix to get this working. I'll remove "needs testing" while I deal with that.

@seadowg
Copy link
Member Author

seadowg commented Sep 22, 2025

@dbemke ok that should all be working now!

@dbemke
Copy link

dbemke commented Sep 22, 2025

ok that should all be working now!

First test - it seems to be working well so I'll add "needs testing" label

try {
val completed =
taskSpec.getTask(applicationContext, stringInputData, isLastUniqueExecution(taskSpec)) { isStopped }.get()
taskSpec.getTask(applicationContext, stringInputData, foreground || isLastUniqueExecution(taskSpec)) { isStopped }.get()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should always count a foreground task as the last execution so that jobs like SyncFormTaskSpec switch to the behaviour they would use in that mode (like notifying about errors).

return if (completed) {
Result.success()
} else if (maxRetries == null || runAttemptCount < maxRetries) {
} else if (!foreground && (maxRetries == null || runAttemptCount < maxRetries)) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to retry when running in the foreground: it doesn't fit with the idea of having more immediate results/feedback, and it also could cause errors (foreground services should not be started in the background).

private const val SYNC_NOTIFICATION_CHANNEL_NAME = "Form updates"

private const val SYNC_NOTIFICATION_ID = 1
private const val SYNC_NOTIFICATION_ID = 3
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like we've made an assumption in the code base that notifications are identified by their ID and their channel. In fact, they are only identified by ID, so this should be unique.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you elaborate on this? Why 3? What was the issue here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is 1, it has the same ID as the error notification (FORM_SYNC_NOTIFICATION_ID) so the error gets cleared when the foreground service hides its notification. We're going to want to work out a centralized source for these IDs, but I wanted to leave that for once we've got tests (#6902).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're going to want to work out a centralized source for these IDs

Yes, this would be important to make it clear. Will that be added to #6902 or a separate issue?

Copy link
Member Author

@seadowg seadowg Sep 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add that to #6902. Right now it's just failing tests (one of which drives out this change). That PR will be the master version of these changes.

@seadowg seadowg marked this pull request as ready for review September 22, 2025 12:19
@WKobus
Copy link

WKobus commented Sep 22, 2025

Tested with success

Verified on device with android 16

Verified cases:

  • Manual refresh after deleting draft from central
  • Wrong project url
  • Airplane mode during form download
  • Successful form download after form download fail

@dbemke
Copy link

dbemke commented Sep 22, 2025

Tested with success

Verified on device with android 10

@grzesiek2010 grzesiek2010 merged commit ada3a13 into getodk:v2025.3.x Sep 23, 2025
6 checks passed
@seadowg seadowg deleted the error-notification branch September 23, 2025 11:03
grzesiek2010 added a commit to grzesiek2010/collect that referenced this pull request Sep 29, 2025
Don't retry tasks when running in foreground
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

behavior verified high priority Should be looked at before other PRs/issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants