We have an application that downloads user contents. Our files could be big ones and usually our users download as batch. Our users having different troubles on download that described below. We want to refactor whole download process and possible use a library for that. We would like your opinion on problems and solutions.
Current Process:
We have list of items, which users can download, each item consists of a single file or multiple files (users don’t aware of that). User can initiate download of an item by pressing the “download button” on the list, and we support concurrent download of items. Remember each item can have multiple files or single file. We also need to show progress of download for items individually. We are using NSURLConnection to download files it was developed since iOS 4.
Problems:
During download if there is a network glitch or some unknown reasons
download gets stuck.
During download lost some data of the file
Having trouble to download in the background (We have to keep screen
awake for example to make download continue etc. since it was
developed on iOS 4)
There is no file integrity check when download is finished
Resume Download
What we need:
Download big files as batch, usually 10 to 50 files, size around 10
to 200 MB of each file
Pause when there is a connection problem (lost, troubled/deadly
slow), auto resume when connection is back
Download in the background (app suspended or closed)
Resume download in background when app is crashed or terminated
Pause, Cancel of Downloads by User
Integrity check when download is complete
Integrity check while download is in progress (on downloaded parts),
auto re-download bad parts before download completes
Getting progress info (list of downloads, downloaded ones, percentage
of download, estimated time of complete, download speed etc.)
Multiple threads to fast download
Support from iOS 7 to Later
In which solution we can make sure each of our needs covered? How can we achieve this?
Ok it can be simply achieved by using NSUrlSession (NSURLSessionDataTask, NSURLSessionDownloadTask) - it will solve all your downloading problems(multiple threads to fast download(concurrent downloading ),resume, pause, cancel and etc.) including background downloads . Also it supports completion block which can be helpful for file integrity check. To check for Internet connection in order to pause or resume downloads you can use Reachability library.
If you wish to use third-party library I stronglly recommend you to use AFNetWorking (everything from your requirements can be done by this library)-->https://github.com/AFNetworking/AFNetworking
Also, this tutorial can be helpfull for your needs - http://www.appcoda.com/background-transfer-service-ios7/
Related
Since there are many places on the Internet talking about Background Fetch in terminated state, some are saying that iOS does not allow anything in that period except working with notifications, location services etc.
Can anyone please give us a final conclusion about this topic, whether the iOS app can work when terminated and what are the limits?
What I'm specifically interested in is file backup. I want to make specific folders in Files periodically (for example each 6h) check if files in it are changed, and if they did, make an API call which will update those changed files on the server. The user should be able to choose which folders he wants. Or for example Photos app, if user gives permission, could we backup the photos from time to time as it works on Google Photos?
These two resources are confusing me a bit, like they are contradictory:
https://www.hackingwithswift.com/example-code/system/how-to-run-code-when-your-app-is-terminated
https://developer.apple.com/documentation/backgroundtasks/bgprocessingtaskrequest
On the first one it says we can run some code when the app is not running for 30 secs, but another says we can execute even longer tasks.
I have an app that records and uploads large files ( up to 5gigs each )
After the recordings are done the user triggers an action to begin the file uploads.
The uploads are registered for background processing so they continue if the phone goes asleep.
I issues I am running into:
Random memory crashes on some files over 4 gigs
Unable to initiate a background upload while the app is already suspended.
So if user records a file between 4-5gigs the app will randomly crash while uploading. Multiple 5 gig files uploading at the same time also increases the chance of crashing.
We currently upload the files in sequence but ran into issue #2 from my list. If the user records multiple 5 gigs files, and puts the phone asleep, only the the first file will upload and the user has to reopen the app for the next file to begin processing.
I have attempted to use BackgroundTasks to see if it can trigger an upload but the background task never fires and I've read the only attempts to fire the background task if it thinks the user is about to use the phone.
I also tried using the urlSessionDidFinishEvents callback on uploadTask. But it never seemed to fire or at least it can't be used to call an API request.
Anyone have advice on initating background file uploads for large files?
I think the problem is that you are likely reaching system resource limits. The system will eject your binary when this occurs; they are called Jetsam events. I suggest you trigger a sysdiagnose event on your device (differs per device - usually pressing volume up, down, and side buttons together).
Then recover the logs from Settings > Privacy > Analytics and Improvements > Analytics Data
The file names begin with sysdiagnose_YEAR.MONTH.DAY_*.
After you copy the files over to your Mac (using the Share button in the iOS UI) you can then look at specifically what is being breached.
Please update your question with specific log information thus retrieved.
Lastly, it is worth implementing applicationDidReceiveMemoryWarning: since your app is probably using a lot of memory during such processing.
Right now we are designing an app in Swift that fetches HTML applications from a server in form of zip files and then run it in the iOS app as an web view. Each zip files is of approx 4-5 mb in size. We have 30+ HTML applications in our app as of now. But we may reach to 150-200 apps soon enough. I would like to know the maximum amount of data that an iOS app can handle. If excess amount of data gets deleted, where will it go? Will it be stored in iCloud before the data gets deleted? Please help me. P.S. The HTML applications will be downloaded from the servers in form of zip files , it'll be extracted and then will be stored as a folder. When the user first installs the app in his system , he won't have any html applications installed. He'll have to fetch the apps one by one according to his requirements.
Since you're saving the content to disk, the limitation is the disk size of the user's device. It also depends on where you're saving the data: If you save to the tmp directories, the data may get deleted, but if you're saving to the application's normal directory it will also be backed up to iCloud (assuming the user backs up).
I would advise against filling up the user's phone with hundreds of MB of data automatically, they will get very annoyed at you. So you will want to offer them a UI to actually select which content they want to keep and which should be removed.
No limit as far as I know.
But be aware that all files you download and store in the app have to be marked as "do not backup in iCloud" - otherwise Apple will reject your binary when you submit it to the store.
See
Apple Documentation and
Excluding files from iCloud Backup
My advice,
Don't download all the applications at once, instead provide user a UI from which he can able to select any application (only one at a time, because at any point he'll be able to run single app only, I guess), then download that particular application (also removed if any previous installed app found).
But wait, there's one more option, you can keep 3 apps at a time, and I believe they wouldn't cost you more than 20Mbs (as you said, 4-5Mbs / app). If so user may have feel of switching between (last used) three apps. If he want any other application then he can select any app, here you need to delete (a app from last three) and add newly downloaded app, this means at any point you'll have 3 apps in your directory.
Now the problem of preserving user information (for individual apps), here you can use any local db (or your server or any third party servers) to store (preserve) user information for particular app. At any point he'll delete the app (you should keep backup of it before deletion will be made).
Later, when he changed his mind, and download the app (previously deleted), then you can restore the information (which was preserved before).
Good luck! Don't wash your hands :)
We have built an in-house Enterprise iPad2+ application that connects to a Drupal CMS, where content (text/images/video) is being delivered to the app via a REST API.
When the user launches the app for the first time, they are prompted to download the content over WIFI network. We are experiencing content failing to download inconsistently i.e. sometimes 60 images fail to download; other times 20 images fail. Since we've added video into the download mix, the content is failing even more often.
Server details:
Windows server
IIS7.5
PHP 5.3
MYSQL5.1
App details:
Require.js: provides JavaScript file and module loading
Backbone.js: provides a frontend JavaScript application framework
Cordova (v2.7.0): Used to provide an environment to run on iOS
Raphael.js: For procedural graphics and animations
jQuery and plugins: For Dom manipulation, animations and interactions
Bootstrap: Base framework for HTML mark-up
Download process is as follows:
User launches app and is prompted to download content
Download begins
The app now makes AJAX call to REST API to fetch content
Upon a successful fetch, the REST API delivers an array of content (text/images/video) - max video filesize 11mb
Content is delivered synchronously
We can add logic to keep retrying upon failure, but this could result in an indefinite loop. The content download size is approx. 50mb, over WIFI.
Our testing:
We have tried from 3 different locations in the world: SA, UK and US and similar issues.
We've tested a 300mb download from the same server, on the same iPad and it downloads fine
QUESTION:
Can anyone tell us why this would be failing?
Could the problem be with a Drupal configuration issue we're missing?
UPDATE 25 August:
We have done some more research and it seems the problem may be a result of iOS Safari timing out at 60secs, and then everything fails after that that to download - see here: http://www.sencha.com/forum/showthread.php?111231-iOS-Safari-Mobile-AJAX-timeout
Has anyone else come across this issue?
We have tried downloading over LAN, and that is 100% fine. WIFI is the issue.
We have tried refreshing the download script after x seconds and resetting the timeout counter. We've tried to detect if a download has failed and to continue retrying it.
Stumped at this point...
UPDATED SOLUTION 28 August:
UPDATED SOLUTION: we have fixed the problem. The issue fundamentally lies in the fact that iOS Safari times out at 60secs. Why? We have no idea... What we were doing was fetching the full list files to download, and then downloading them synchronously. What happened at 60secs, is the download times out and we were losing our file list. What we did to resolve this, is we saved the files not downloaded list at 60secs, then started the download process again with this new list, and repeated this process until all files successfully downloaded.
This is a followup to : MonoTouch: How to save a huge PDF downloaded from an URL incrementally?
I'm trying to follow the guidelines indicated by the Apple slides of the Newsstand presentation ("Building Newsstand Apps", Session 504):
http://adcdownload.apple.com//wwdc_2011/adc_on_itunes__wwdc11_sessions__pdf/504_building_newsstand_apps.pdf
Apple recommends the use of the NSURLConnection Delegate and NKAssetDownload for downloading and resuming the newsstand content, but I don't understand what C# code in MonoTouch is equivalent to the one in Obj-C showed in the slides.
The problem is how to download a huge PDF file from an URL in my MonoTouch iPhone/iPad newsstand app, a PDF that is often too big to fit in memory.
To execute the download incrementally as indicated in the slides, instead of appending all the downloaded data in NSData and at the very end of the download and store it to a file when I got all data, I need to execute the download asynchronously in a separate thread and append to a file each received chunk and free my memory.
At the same time I need to be certain that if the connection is dropped or the app crashes the download would resume automatically from the last chunk without corrupting the file.
What is the better way to handle this in MonoTouch, without risking to see my App rejected by Apple?
Thanks in advance!
A sample showing how you setup the NSUrlConnectionDelegate can be found here:
https://github.com/xamarin/monotouch-samples/blob/master/HttpClient/Cocoa.cs
That code shows how to create an NSUrlRequest, and how to pass an NSUrlConnectionDelegate (it is the "this" parameter in line 32).
The sample overrides a handful of methods from NSUrlConnectionDelegate, you would likely override more, based on what you want to support.