I know there is NSURLSession class which is launched in iOS7 and it does have NSURLSessionUploadTask for uploading data to server, But I need to know whether it will continue uploading even after in background mode if no? then what to do for continue that task in background mode too for complete uploading.
previously we can use beginBackgroundTaskWithExpirationHandler: and endBackgroundTask: which will continue that task to max 10 minutes for iOS6 but in iOS 7 and above it will hardly run upto 3 minutes (as per my knowledge).
So can you please help me guys for any solution or example if available.
The answer for your first question is probably YES, you can continue uploading for the tim e that is permitted by the iOS but for that you need use UIBackgroundTaskIdentifier to get hold of that extra time.
And for the second part of your question for uploading the remaining images when the app is not running you can use Background fetch. When you enable Background fetch the app regularly downloads and processes small amounts of content from the network. So probably by combining UIBackgroundTaskIdentifier and Background fetch you can achieve uploading the images in background.
Below mentioned are the steps to combine UIBackgroundTaskIdentifier and Background fetch.
First let's initialise UIBackgroundTaskIdentifier
-(void) beginBackgroundUploadTask
{
if(self.backgroundTask != UIBackgroundTaskInvalid)
{
[self endBackgroundUploadTask];
}
self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[self endBackgroundUploadTask];
}];
}
Once the background task runs out of time from the stipulated allotted time, we should invalidate and end the background task.
-(void) endBackgroundUploadTask
{
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask ];
self. backgroundTask = UIBackgroundTaskInvalid;
}
Do not forget to enable Background Modes in Xcode → Select Project File → Capabilities → Check the Background fetch checkbox.
For further info you can refer the link below:
http://mobisoftinfotech.com/resources/mguide/background-fetch-ios/
Related
I know there are hundreds of topics out there concerning the background fetch on iOS. I simply cannot solve my problem to get the background fetch for my app to work. It is absoulutely substantial for the outcome of my app to have a working background fetch. My background fetch works fine on the simulator via Debug -> Simulate Background fetch and also on device with the special scheme setting: "Launch due to a background fetch event". I know that it doesn´t gets executed when the user is force quitting the app. I tried to lock the iPhone and wait for hours then unlock it to try to trigger the background fetch. Nothing happens. Actually everything works fine but the background fetch simply NEVER gets executed on my iPhone. I know that iOS has a special algorithm for calling background threads so a little patient is needed. But after 2 months of waiting for a background fetch to happen automatically I don´t have patients anymore. What I did:
App capabilites: Background fetch activated
Info.plist: Required background modes: App downloads content from the network
App delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([UIApplication instancesRespondToSelector:#selector(registerUserNotificationSettings:)]){
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
}
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:2.0];
return YES;
}
- (void) application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
//Do my stuff
completionHandler (UIBackgroundFetchResultNewData);
}
Did you check out to go Settings->General->background app refresh and check if its enabled?
It could be the problem...
We're currently developing an iOS app that needs to check location in the background. At first, we tried to use significant location changes, but they aren't accurate enough/don't trigger often enough. We considered using region monitoring, but from what I've read online, that isn't always accurate either, and you also have the problem of a limited number of regions to monitor. (We may eventually try region monitoring.) At the moment, however, we're attempting to use the standard location updates to track the user location in the background, with a plan to have it at check at intervals of 5 minutes, or so.
The app is registered for location updates in the background (using 'App registers for location updates' for 'Required background modes'), and we start a background task which checks the location once, stops location updates, then uses NSThread sleepForTimeInterval: to (at the moment, while we're in development) pause the task for 10 seconds. It then checks the location once again, stops location updates, pauses for 10 seconds, etc.
This appears to work as expected... When the app goes into the background, we receive a log/notification with our location update every 10 seconds, and when the app is reopened, the logs/notifications stop. However, the problem is that when the app then goes into the background for a second time, it appears the original background task was never cancelled, and a new one is created, so there are now two tasks running, each checking location at 10 sec on intervals. If the app is opened/sent to the background multiple times, then a background task is started for each of them.
I thought about setting a flag to say "has the app been sent to the background at least once?", and only run the task if it's the first time it's sent to the background, but this seems to cause additional problems, and (as a relatively new iOS developer) I'm curious as to why the background tasks aren't being cancelled when the app enters the foreground.
The AppDelegate.h file contains...
#interface AppDelegate : UIResponder <UIApplicationDelegate, CLLocationManagerDelegate> {
UIWindow *window;
UINavigationController *navigationController;
UIBackgroundTaskIdentifier bgTask;
BOOL inBackground;
}
The AppDelegate.m file contains...
- (void)applicationDidEnterBackground:(UIApplication *)application {
inBackground = YES;
bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
while (inBackground == YES) {
NSLog(#"%#", #"Check location...");
[locationManager startUpdatingLocation];
[NSThread sleepForTimeInterval:10];
}
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
inBackground = NO;
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
The location updates are working as expected, I just can't work out why the background tasks aren't being cancelled/ended when the app enters the foreground. I do wonder if it's anything to do with the NSThread sleepForTimeInterval:, but I'm not sure if it is, or how to fix it (if indeed, it is). Thanks, in advance, for any help!
You don't manage location updates by sleeping and then requesting them. You manage location updates by setting "location" in UIBackgroundMode (as you do), and then implementing a CLLocationManagerDelegate. This has nothing to do with beginBackgroundTaskWithExpirationHandler:. That's for requesting additional time (up to about 10 minutes) to finish a given operation. You shouldn't be calling that at all just to get location updates.
Once you've registered as a location app in UIBackgroundMode, you will automatically get updates whenever the location changes within the accuracy you specified for your location manager. The system will do all the work for you.
What you're describing may actually hurt battery life because it frustrates the OS's ability to manage the multiple location sensors (of which the GPS is just one). Tell the OS what you need by setting the correct accuracy (if significant changes is too coarse), and let it do its job. Getting really accurate location from the GPS is expensive. You should do battery testing before assuming that it's cheaper to do every 5 minutes than to leave on. The best thing you can do to preserve power is to reduce the required accuracy. You might turn it down to a coarse level, and then when you come to the foreground move it to an accurate level. But keeping track of precisely where the user is every 5 minutes is going to be expensive. It's hard to fix that.
BTW, what you're really trying to do here is get to run "something" every 5 minutes. There is no mechanism for that in iOS. You can either ask for location services or not (and configure it in various ways). You can't ask for "I want to wake up every five minutes and ... do anything." After about 10 minutes you're going to be killed if you don't call endBackgroundTask:.
To your question of why the tasks aren't being cancelled, see How to use beginBackgroundTaskWithExpirationHandler for already running task in iOS. As I said, this "background tasks" is not the tool you want for this problem. It's completely unrelated.
I'm fairly certain that your instance variable bgTask is being reallocated when the app comes back into the foreground, so the value doesn't contain the identifier you're looking to kill. Consider saving this identifier in NSUserDefaults or something a little more permanent and retrieving it later.
I'm writing following code that opens browser when app will be going to background:
- (void)applicationWillResignActive:(UIApplication *)application
{
/*
Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
*/
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"http://www.google.com"]];
}
but its not opening. Any suggestions?
Can I open browser in "applicationWillResignActive" or not?
You code looks fine so I guess that iOS won't let you do it. Your app has been told to go into the background - you don't get to open new apps!
PS :
Why would you ever want to do this - surely this will just really really annoy the user?
When you open up an app and press home screen again, the app is obviously in te background. When you open other apps and wait a time, the views of my app have been unloaded (like UITableView reloads data).
Is there some sort of notification or how do I know whether my app is about to release their views? Is it just viewDidUnload?
This link should help: iPhone Development - Simulate Memory Warning
Basically you received a memory warning and parts of the view got unloaded.
unfortunately, when you app is put in the background it is frozen and it will not receive events. Unless you have requested some background processing time and have provided the system with a background processing task Expiration Handler:
backgroundTask_ = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
// Peform clean up work
// Mark the task now as invalid
[[UIApplication sharedApplication] endBackgroundTask:backgroundTask_];
backgroundTask_ = UIBackgroundTaskInvalid;
}];
in which case, after the extra, undetermined amount of processing time is over, the expiration handler will be called.
Some good background docs can be found here App States and Multitasking. But even then you won't be able to do much in the way of cleanup.
Good luck
I'm using NSURLConnection to download resources asynchronously in iOS. (They are large-ish PDF files, so it takes some time on a slow connection.)
Now I'm updating my app from iOS 3 to iOS 4. As my app is none of location-aware, voip, and background music, I guess I need to do something.
My question is, then, what happens to the NSURLConnection currently running? Is it suspended and magically resumed when the app comes back to the foreground, or is it outright killed? If it is the latter, what is the standard strategy to resume it automatically later? Is there a open-source subclass of NSURLConnection which automatically does that?
You can start a task that will run for at most 10 minutes. Look at using the beginBackgroundTaskWithExpirationHandler: API for this purpose. Just be aware, if your task takes too long, it will be killed by the OS.
The NSURLConnection is indeed suspended and started again when the app enters the foreground. Just make sure you kill the connection if the app moves from suspended to not running like so:
- (void)applicationWillTerminate:(UIApplication *)application {
if (self.downloadConnection != nil){
[self.downloadConnection cancel];
}
}