-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
5128: Fix stuck uploads #5257
5128: Fix stuck uploads #5257
Conversation
Thanks! |
Trying in Restricted mode, I am getting failures, and retry does not seem to work: screen-20230709-211850.mp4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just leaving some comments based on my initial observation.
@@ -540,7 +541,11 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) : | |||
val intent = Intent(appContext,toClass) | |||
return TaskStackBuilder.create(appContext).run { | |||
addNextIntentWithParentStack(intent) | |||
getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT) | |||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { | |||
getPendingIntent(0, PendingIntent.FLAG_IMMUTABLE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC, I believe we should be keeping both the FLAG_IMMUTABLE
and FLAG_UPDATE_CURRENT
flags [ ref ]. Is there any reason behind not sending the FLAG_UPDATE_CURRENT
here? Have you explored on what difference including / not including it makes ?
@@ -540,7 +541,11 @@ class UploadWorker(var appContext: Context, workerParams: WorkerParameters) : | |||
val intent = Intent(appContext,toClass) | |||
return TaskStackBuilder.create(appContext).run { | |||
addNextIntentWithParentStack(intent) | |||
getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT) | |||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While the mandate has been since Android S, can we not send the flag for VERSION_CODES.M
and above since the IMMUTABLE flag is available since that version?
Thank you for testing, I'll fix this. I'd read about these possibilities related to |
I could not manage to get the retry button, it simply restarts the process on my Android 12 device. I have modified the flag and version code, though. |
app/src/main/res/values/strings.xml
Outdated
@@ -75,6 +76,9 @@ | |||
<string name="login_success">Login success!</string> | |||
<string name="login_failed">Login failed!</string> | |||
<string name="upload_failed">File not found. Please try another file.</string> | |||
<string name="retry_limit_reached">Maximum retry limit reached! Please cancel the upload and try again</string> | |||
<string name="unrestricted_battery_mode">Turn battery optimisations off</string> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add a ? at the end to make it friendlier. Also, "optimization" (singular not plural) is less freightening and reflects the wording in the OS settings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, I'll use 'z' instead of 's' everywhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah sorry, I only meant about the singular. Either optimization or optimisation is fine for me 😊
app/src/main/res/values/strings.xml
Outdated
@@ -75,6 +76,9 @@ | |||
<string name="login_success">Login success!</string> | |||
<string name="login_failed">Login failed!</string> | |||
<string name="upload_failed">File not found. Please try another file.</string> | |||
<string name="retry_limit_reached">Maximum retry limit reached! Please cancel the upload and try again</string> | |||
<string name="unrestricted_battery_mode">Turn battery optimisations off</string> | |||
<string name="suggest_unrestricted_mode">Uploading more than 3 images works more reliably when the battery optimisations are turned off. Please turn battery optimisations off for the Commons app or fr.free.nrw.commons from the settings for a smooth upload experience. \n\nPossible steps to turn battery optimisation off:\n\nStep 1: Tap on the \'Settings\' button below.\n\nStep 2: Switch from \'Not optimised\' to \'All apps\'.\n\nStep 3: Scroll to find the Commons app or fr.free.nrw.commons.\n\nStep 4: Tap it and select \'Don\'t optimise\'.\n\nStep 5: Press \'Done\'.</string> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The first "or fr.etc" is not needed I think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few minor suggestions
@@ -138,6 +148,9 @@ public void onCreate(Bundle savedInstanceState) { | |||
setTitle(getString(R.string.navigation_item_explore)); | |||
setUpLoggedOutPager(); | |||
} else { | |||
if (applicationKvStore.getBoolean("firstrun", true)) { | |||
applicationKvStore.putBoolean("firstBigUploadSet", true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I appreciate the consistency with firstrun
, but it is troubling to have firstBigUploadSet being true during small uploads.
How about renaming it to hasAlreadyLaunchedBigMultiupload
and inverting true/false?
It would be easier to understand, I believe.
Thanks!
@@ -364,6 +376,24 @@ private void receiveSharedItems() { | |||
.getQuantityString(R.plurals.upload_count_title, uploadableFiles.size(), uploadableFiles.size())); | |||
|
|||
fragments = new ArrayList<>(); | |||
// Suggest users to switch to Unrestricted battery usage mode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Append when uploading more than a few files. That's because we have noticed that many-files uploads have a much higher probability of failing than uploads with less files.
getString(R.string.title_activity_settings), | ||
getString(R.string.cancel), | ||
() -> { | ||
Intent batteryOptimisationSettingsIntent = new Intent( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a comment about the library you tried, explaining how it did not make the setting dialog appear on Pixel nor Xiaomi. Someone may want to revisit that in the future.
app/src/main/res/values/strings.xml
Outdated
@@ -75,6 +76,9 @@ | |||
<string name="login_success">Login success!</string> | |||
<string name="login_failed">Login failed!</string> | |||
<string name="upload_failed">File not found. Please try another file.</string> | |||
<string name="retry_limit_reached">Maximum retry limit reached! Please cancel the upload and try again</string> | |||
<string name="unrestricted_battery_mode">Turn battery optimization off?</string> | |||
<string name="suggest_unrestricted_mode">Uploading more than 3 images works more reliably when the battery optimization are turned off. Please turn battery optimization off for the Commons app from the settings for a smooth upload experience. \n\nPossible steps to turn battery optimization off:\n\nStep 1: Tap on the \'Settings\' button below.\n\nStep 2: Switch from \'Not optimized\' to \'All apps\'.\n\nStep 3: Scroll to find the Commons app or fr.free.nrw.commons.\n\nStep 4: Tap it and select \'Don\'t optimize\'.\n\nStep 5: Press \'Done\'.</string> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are turned off
-> is turned off
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I should have read the sentence again after removing the 's' :')
…me firstBigUploadSet
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good work overall. Well commented and relevant TODOs added. Please check the comments.
app/src/main/java/fr/free/nrw/commons/contributions/ContributionsPresenter.java
Show resolved
Hide resolved
app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java
Show resolved
Hide resolved
will never be successful */ | ||
if(retries < MAX_RETRIES) { | ||
contribution.setRetries(retries + 1); | ||
Timber.d("Retried %d times", retries + 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can it be changed to "Retried upload %d times" so it's clear what we're trying to retry?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed the debug log line could say that, and also say what file, because often several files are being retried at the same time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've left a couple of comments based on my initial look at the changes. Kindly take a look.
Also, have you checked the interaction of these changes with the "Limited Connection mode" @RitikaPahwa4444 ? Do they work as intended even after these changes ?
/** | ||
* Number of times a contribution has been retried after a failure | ||
*/ | ||
var retries: Int = 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a schema change to the contribution table and requires a bump of the db version number [ref]. Kindly take care of the same.
if (uploadableFiles.size() > 3 | ||
&& !defaultKvStore.getBoolean("hasAlreadyLaunchedBigMultiupload")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess we should show this dialog only for relevant Android versions. The intent itself is only available since API 23 (6+). Kindly check and make sure we only invoke this for the relevant Android versions.
I often switch to limited connection mode, never found any of these changes interfering with its behaviour. Will test more since you feel these changes could affect its functioning👍🏻 |
Timber.d("Restarting for %s", contribution.toString()); | ||
if (contribution.getState() == STATE_PAUSED || contribution.getState()==Contribution.STATE_QUEUED_LIMITED_CONNECTION_MODE) { | ||
restartUpload(contribution); | ||
} else if (contribution.getState() == STATE_FAILED) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was trying to test the change in my device. Blindly retrying all failed uploads does seem to be affecting the UX badly. The app seems to just retrying genuinely failed uploads again-and-again each time I open the app.
Is there really no other attribute that we have that could help with identifying if an upload failed for a genuine reason? (I'm presuming its because of beta cluster not supporting stashed uploads).
Also, I remember cancelling all uploads manually one time. The cancel didn't seem to have worked. Has anyone else observed this too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested on 100+ pictures, this pull request brings a great improvement in upload reliability.
The code also looks good to me.
Closing this as these changes have already been merged with #5272. |
Description (required)
Fixes #5128
What changes did you make and why?
Uploads often get stuck when users turn their screen off or simply navigate away from their screen, especially when the battery usage for the app is not set as "Unrestricted".
FLAG_IMMUTABLE
withPendingIntent
for version code S and above. Android has made it mandatory for apps targeting S+ (API level 31 and above) to pass eitherFLAG_MUTABLE
orFLAG_IMMUTABLE
withPendingIntent
(based on my logcat error).The above changes apparently fixed stuck uploads. The uploads, however, still fail with a
SocketTimeoutException
.onResume()
so that failed uploads resume as soon as the user returns to the app. The code related to this may be improved with correct usage of WorkManager, but I need to investigate its behaviour on various devices under different network and battery conditions.Key improvements:
Uploads no longer remain stuck and resume automatically in case the user returns to the app within 2 minutes (the connection time associated with the
SocketTimeoutException
). After 2 minutes, a "Failed to upload" notification is shown for all the uploads but these failed uploads, too, start as soon as the user returns to the app because of the retry logic.This may not be the best solution, so I'm adding a WIP/Draft status to it.
Further improvements I am looking forward to:
I'll be researching more about network conditions when the screen is turned off. Even if Android provides a small window to resume work under "Optimised" battery conditions, we can fix the
SocketTimeout
issue.Tests performed (required)
Tested prodDebug on Moto g62 with API level 31.