Downloading heavy data from server using separate thread - iphone

We are building an iPhone app and we are having a problem with downloading in-app purchases in the background and I was wondering if anyone had a solution …
Our in-app purchases are quite big 35-40mb, each purchase consisting of 5 items each 7-8mb so the phone typically goes into standby or the user switches apps before the purchase is downloaded so it is essential the in-app purchases are downloaded in the background seamlessly.
When we download the purchase we have to download about 35-40mb from the server and simultaneously update the local sqlite database in the app. We have tested downloading the items in the foreground and its working fine and we have done some handling to keep the download process continuing in the background and the download is continuing and we can see it working in the debugger.
However we have the following issue …
User starts download
Download page on app shows that the app is downloading
User leaves app or phone goes into standby
User returns to app
At this point the app splash screen loads and stays on the screen until one of the 8mb downloads has completed, when completed it then switches to the download page on the app. This is really confusing for the user as they think the app has crashed.
So how can we manage the in-app purchase so that when the user presses download it starts the download in the background and the app behaves as normal while the download is in progress? So user leaves app and when they return it shows the correct page with download progress. User navigates within app and it works fine.
Some observations ...
I have to run the NSURLConnection consecutively five times to perform downloading, because each in-app purchase has 5 items.
The thing I noticed is that when the first download is in progress the "didEnterBackground" method doesn't get called even if the user presses the home button but after the 1st download process is completed then "didEnterBackground" method does get called. And if the user puts the app into the background and then returns to the foreground the "didEnterForeground" should be called but it isn't.
I am downloading data using a different thread then "MainThread" ,but still running in same issue.
Any help would be much appreciated.

Have a look at AFNetworking it's used by many and loads on different thread. In the readme there's an file-download-with-progress example.
You can prevent iOS going into standby mode during download:
[UIApplication sharedApplication].idleTimerDisabled = YES;

Try to look at... a new AFNetworking'extension AFDownloadRequestOperation
This class has additional support to resume a partial download, uses a temporary directory and has a special block that helps with calculating the correct download progress, etc
"Don't forget to set shouldResume to YES" :)
For AFDownloadRequestOperation you can check also this AFNetworking not resuming download
UPD
in the worse case.. you can try "Task Completion for Long-Running Tasks" or "Task-Specific Background Processing" in background.. http://www.codeproject.com/Articles/124159/Hour-21-Building-Background-Aware-Applications

Related

Automatically sync with central database

I have developed an application. My application takes feedback from users. When network is not available, then that data is saved in local db. But, once the network is available, it will sync automatically with the central database.
But, I have some problem here. If I save database & send my application to background, once the network is available, it has to automatically do this syncing with the central database. How to do that?
I am using Reachability class to check network availability.
At the present time there is no way to have your app "wake up" when the network becomes available. If the user quit your app without a network connection, you cannot do anything until they voluntarily open your app.
However, you can prompt them to do so using UILocalNotification. If your app is being quit and you have some data waiting to be uploaded, you can schedule a notification to fire in 4 hours (or whatever amount of time makes sense).
If the user opens the app before the notification time and you are able to upload the data, you can cancel the notification and no one will ever know it was scheduled.
If the user does not open the app, the notification will appear, and say something like, "You have data on your phone that you have not uploaded in a while. Connect to the Internet and launch MyAwesomeApp to sync your data."
You cannot do it on iPhone. Your app ceases to exist in a few seconds (once the app moves to the background).
I believe its 5 seconds for all apps, 10 mins for some apps that have requested for more background time.
PS: Unless, you mark your app as a navigation or a music app, which can stay on in the background, theoretically, forever. But I doubt if a feedback app can get approved on the appstore with such permissions.
Keep an additional column in your saved database which marks successful uploading of your data to your server. Set this when the data is written, but not yet uploaded. When it's successfully uploaded, clear the value. You can check this value when your app comes to the foreground, and have it upload any data that hasn't had this column cleared. While your app is running, you can set a timer for an appropriate interval to recheck reachability and if successful, attempt an upload. Only clear your flag when the data is successfully written, and make sure your server doesn't try to process a partial upload (think of someone trying to do this on a subway or train, moving in and out of connectivity).

IOS background work

I have an iPhone application like facebook for iPhone. My application must connect my server and read all message every two hours regularly. I have a thread to read all message but when the application is terminated the thread cannot work. Can the thread run undependently from main delegate or how can I find solution for this problem?
You cannot have your app do stuff in the background. There is an API to finish tasks like uploading a photo but even that will be killed after around 10 minutes.
But the Apple Push Notification Service seems like the most appropriate solution for your problem. Your server notifies the device that there is something new happening and you fetch the actual messages when the user opens the app.
edit: As of iOS 7 Apple implemented a feature where you can schedule running tasks to fetch data in the background. Those tasks are not guaranteed to run at any specific times. See the release notes for iOS 7 and the linked methods below:
Apps that regularly update their content by contacting a server can
register with the system and be launched periodically to retrieve that
content in the background. To register, include the UIBackgroundModes
key with the fetch value in your app’s Info.plist file. Then, when
your app is launched, call the setMinimumBackgroundFetchInterval:
method to determine how often it receives update messages. Finally,
you must also implement the
application:performFetchWithCompletionHandler: method in your app
delegate.
There is no solution.
Apple does not permit applications to run in the background unless they are of a specific type such as location or audio or voip or newstand (your app can continue to run for about 10 minutes after it was active if it uses shouldBeginBackgroundTaskWithExpirationHandler).
There is no workaround, many many other people have wondered how to do the same thing as yourself before, but there is no legitimate way. Your app cannot schedule any sort of periodic call home activity.
The only way your app can run once its gone into a suspended or terminated state is for the user to launch it, either explicitly or in reponse to a local notification or remote push notification.

iOS app: Uploading multiple files in the background

For iOS, I am aware that apps can upload in the background, as according to this thread:
Uploading in background thread in iOS
When I refer to "background", I mean the user has clicked the home button, using another app, or the phone's screen is off.
Follow-up Questions:
1.
Is there a timeout limit to the background uploading? This may be an issue if the file being uploaded is huge.
2.
Is it possible to upload a list of files in the background, or does it only support the finishing of one upload that was in progress before the user switched to another app?
3.
I suppose if the user quits the app completely, the upload will be stopped? Quitting completely as in, user double clicks home button, touches and holds down on the app until it starts shaking, then clicks the "X" to shut it down.
Answers:
1) The timeout limit is probably server - imposed, but you can certainly add some timeout detection code on the client (iOS) side.
2) Uploading a "list of files" is effectively the same as uploading a file. A list of files is just another file, effectively.
3) If the app is killed, yes, everything (and all the background threads) get killed along with it.

iphone - Connecting to server in background

I'm creating an app which connects to server and sends some text.
If network (both wifi or 3g) is there, it will immediately send the text to server.
But if there is no network, it keeps on polling for server connection every 5 minutes.
All this part is working fine.
But when using iPhone 4 device, i want the app to check for server connection even when app goes into background. So, when app goes to background and when network comes back, it must be able to send the text to server.
How can I achieve it? I've seen some apps where they say that the app will upload photos to server even in background. How will they do it?
I suggest you read this article from Apple carefully, especially the Completing a Finite Length Task in the Background section.
http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/BackgroundExecution/BackgroundExecution.html
Something to clarify:
Once your app is in the background and is frozen by the OS, there would be no way for your app by it self to wake up and re-connect to the internet.
However, according to the article above from Apple, you can call this beginBackgroundTaskWithExpirationHandler method from your app's delegate to apply for additional time when put in the background, which is to say, though your app cannot wake up by it self when in background, it can, when in the background and not frozen, try to apply for additional time to finish its lengthy task.
Hope it helps.
There is a trick that I think flayvr is using.
If you download and use the app, you will see that they require you to enable your location.
And why is that?
because they want like you to do something in the background even when the app is terminated (they creating an album out of your newly captured photos), and how do they do that?
They use the significant location change, where when someone is traveling some significant distance (something like 500m) each app that registered for significant location change will get awaken for a limited amount of time to perform some quick task and will be terminated in a few seconds.
So your app can register to that event also and when the event of significant location change fired you will be able to send the text to server (quickly).
Hope that helps.
Until now you can do that on iOS7 with Background Fetch.
Take a look at this article.
However you only have up to 30s to get the task done.
According to the article above, there's also another solution called Background transfer service.
If more time is required though, then the Background Transfer Service
API can be used
Create a new project in Xcode and you will see there are bunch of new methods auto generated in app delegate file. like applicationDidEnterBackground, applicationWillEnterForeground etc.
read the description you have to call your thread to upload data on server here.

Is there any system level background queue process in iPhone?

I need to save a big file, sometime it takes a very long time to finish, user might just close the application. I am wondering whether the iPhone SDK could take over the unfinished big task.
Appears iPhone's own mail system could do background send. I prepared a email, click send, then close the mail app immediately. In home page, after several seconds, I heard a sound and the email was delivered.
You're out of luck. Only Apple's own apps are allowed to operate in the background. But I think your app gets some time to finish up when the user closes the app.
You can't run the app in the background as PEZ says. However you could spin off a thread to perform the task and then at least the user can get on with doing other things in your application.
If I remember correctly, your app gets 5 seconds between the user pressing the home button and the iPhone OS killing it if you're not done.