-
Notifications
You must be signed in to change notification settings - Fork 886
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
How to implement background uploads and offline support correctly #1047
Comments
Sorry to hear that you are running into difficulties using the SDK. Let me take a crack at answering your questions here
The sample does not cover what needs to be done if the app were to be restarted. I will address that in the documentation as well, but here is a short summary of what needs to be done
Hopefully this gets you unblocked. I will post back in this thread once the documentation updates have been made. |
Thank you so much @cbommas! I will dive deeper into this on Monday, but wanted to answer your question. In regards to offline mode support, I was wondering if the transfer utility will automatically stop uploading once the internet connection is lost, and automatically start uploading again once it is restored. If you try to start an upload while offline, does it successfully upload eventually if you later return to the app with an internet connection, or would it just fail immediately? I saw there's a retryLimit you can configure and I've set that to 5, but wanted to make sure it's not just going to continually try and fail 5 times in rapid succession if it's attempted to upload while offline. It sounded like it does have support for this functionality from what I've seen outside the documentation. Then in regards to calling |
Yes, I was mistaken about the I will work on your question regarding offline and will post an update here in the next few days. |
Thanks! I believe I have now implemented everything needed for uploading photos! I tested background transfers and that appears to be working nicely. I'm now testing force quitting the app before transfers are completed to test the process of restoring the progress and completion blocks. It appears the uploads are not starting after doing so. The progress block is never called after that, nor the completion block, for either of the two uploads that were ongoing before the force quit. Inside
|
Good to hear that you have been able to get things working. Here is what is going on with the force close - When you force close the app, the tasks in the NSURLSession are canceled by iOS ( see https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1407496-backgroundsessionconfigurationwi for more details). I believe that the transfers are going into an "Unknown" state as the TransferUtility is unable to find them in the underlying session. You can check the status using |
Aw okay. Yes the status is indeed unknown. So what would be the right way to go ahead and restart uploads in this scenario? Is there a way to 'naturally' test this process where we need to reassign the blocks, since force quitting actually cancels them? |
A couple of options come to mind - a) you could put the transfer request back on the UI (all transfers that have a status of unknown) upon the UI and have the app user try them again b) you could automatically create a new transfer request for each task in an unknown status and track them on the UI. The right answer depends on your use cases/scenarios. Let me know if you have further questions. |
👍 I think my only questions remaining are in regards to behavior when offline, returning online, etc. I'll look forward to hearing about that and let you know if I have any further questions in the meantime. I appreciate your help! |
@hipwelljo
My findings were as follows
|
That's good to hear thanks! In the case where an internet connection is poor and it fails to upload (not using multipart), does it call the completionHandler with an error object, and then make the request again, and repeat until the retryLimit is exceeded? Thus we could expect to receive up to 10 errors. Or does it not call the completionHandler with an error until it has exceeded the retryLimit? Once a task has errored, its status will be AWSS3TransferUtilityTransferStatusError. Does this task persist between app launches? So on app launch is it appropriate to check if there's any tasks with an error status and recreate the uploads (or inform the user in the ui), similar to what we're doing with the unknown status? When do the tasks get cleared from the device? I am wanting to make sure we don't enter into a state of limbo where transfers are lost. |
@hipwelljo For the second question, tasks that are completed successfully or errored out will not be persisted between launches. If the transfer was in progress and did not get to an end state before the app was terminated, it could be in a number of states
To summarize, the TransferUtility will only keep track of the transfer state for a transfer until the transfer reaches a terminal state. After that, it will still keep the state in memory (as a convenience mechanism) for the current app session, but will not persist it between app launches. |
Thanks! A follow-up question: when it fails to upload but has not yet met the retryLimit, does it use the same transferID to try again, or does it gain a new transferID? |
Once a transferID is assigned to a transfer, it is never changed. It will keep the transferID until the retries are exhausted. |
@hipwelljo Thank you for your patience and for working with me to resolve these issues. |
@cbommas Thank you! |
I can think of a couple of reasons why it went into error status.
In any case, you can use this code snippet get more details on the error.
Also, if this doesn't help resolve the issue, it will be great if you could create a new issue and we can track it there. |
@cbommas Thank you for quick reply! I've found that printing I've enabled verbose logging and what I've found here that
Code -999 means that task was cancelled, What I expect is that AWSS3TransferIUtility's BTW, using resume data above you can resume download process by invoking
Thanks! I can create an issue if this is possible to resolve. |
@cbommas Just checking that you've read my comment above. |
Sorry, I missed seeing this. I am not sure that resumeData will work, but am happy to give it a shot. |
@scb01 Forgive me for resurrecting this years later, but I'm seeing issues with handling when a download spans app termination and relaunch. I'm stopping execution in Xcode as a proxy for iOS background termination - I'm assuming this is not the same as the user force quitting, as sometimes I am able to continue a download doing this whereas force quitting should always cancel download sessions. I'm having problems consistently obtaining pre-existing download tasks in order to reconnect handler blocks. I would like to do this manually because I also take this opportunity to reconnect handler blocks on the download task progress object:
configureAndTrackDownloadTask: sets the task.progress pausingHandler, resumingHandler and cancellationHandler, and then sets the progressHandler and completionHandler of the download task. It also begins tracking the progress object internally. I find that it is very rare for any pre-existing download to be logged on relaunching the app, either by simply stopping execution and restarting in Xcode while the download is running (in foreground or background), or by turning on airplane mode first to ensure the download does not complete before relaunch. If I add the following code before attempting this:
then I find that I have better luck. Bear in mind that I need to set the task.progress handlers before I set the handlers on the task itself for internal logic related to the fact that the task completionHandler does not execute for cancelled downloads. That is why I'm passing nil - examination of AWSS3TransferUtility code leads me to believe that setting a non-nil completionHandler will fire it immediately if the task already completed which is undesirable in my case because I need the task.progress handlers to be set before the completionHandler can be run. To recap this slightly rambling post, my question is this: on app launch, will it suffice to register the transfer utility and then enumerate the result of getDownloadTasks and set all block handlers manually, or is there some other magic connected to using enumerateToAssignBlocks: which I have failed to recognise looking through the source code? It just seems like the former method often fails to find download tasks that should be present during testing whereas I have better luck when executing enumerateToAssignBlocks:blocks, however the latter doesn't provide a way to assign task.progress-centric handler blocks prior to setting handler objects on the task object itself (unless you pass nil for those blocks and run enumerate first, which is somewhat messy). |
State your question
I'm looking through the documentation on how to utilize the AWSS3TransferUtility to upload files and support background uploads for an iOS app, and resume them should the app be terminated and relaunched. It appears the documentation is incorrect when it comes to Background Transfers information. It states the code is suspending a transfer when the app is about to be terminated, but that's not what it does, the code suspends it in the contiueWith block - right after it started the upload. The next section, Manage a Transfer when a Suspended App Returns to the Foreground, states "When an app that has initiated a transfer becomes suspended and then returns to the foreground, the transfer may still be in progress or may have completed. In both cases, use the following code to reestablish the progress and completion handler blocks of the app" but it doesn't explain where this code should go - in the AppDelegate willEnterForeground, didBecomeActive, didFinishLaunching, elsewhere?
Trying to research how to do this the correct way I'm finding conflicting information. From what I've gathered so far reading in GitHub issues (for example, here), you don't actually need to reassign completion blocks unless the app is terminated, and you need to do it a different way not using enumerateToAssignBlocks, but again it's not explained where to put that code. We also don't need to call interceptApplication anymore? So it appears almost all of the documentation is out-of-date.
I would also like to understand what offline mode support there is. It sounds like it may be in place now, but maybe with only the multi-part uploads.
Unfortunately the sample project doesn't implement the background transfer support or anything except a basic upload, so I haven't found an example project that implements this functionality.
In short, I'm finding no information out there on the right way to piece together these APIs with the latest versions of the SDK.
Can you please update the documentation, and ideally update the sample projects? And if you can provide correct and up-to-date information here in the mean-time that would be great! Surely many others will find this useful. Thanks!
Which AWS Services are you utilizing?
AWSS3
Provide code snippets (if applicable)
Environment(please complete the following information):
Device Information (please complete the following information):
The text was updated successfully, but these errors were encountered: