Hi all using following code for background task it works fine ,when iPhone is connected with xcode , but when I ran the app without connected xcode ,then background tasks won't work
- (void)applicationDidEnterBackground:(UIApplication *)application
{
back=1.0f;
NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];
NSRunLoop *runLoop=[NSRunLoop currentRunLoop];
timer=[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(changeCounter) userInfo:nil repeats:YES];
[runLoop run];
[pool release];
}
Please help why this is happening
have you checked the documentation for background executation?
you should start the task like:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UIApplication* app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do the work associated with the task.
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}
http://developer.apple.com/library/ios/#DOCUMENTATION/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html
Related
I have a voip application.
I am using UILocalNotification in my application to alert notification for incoming call when application in background.
When application is in background, after getting an incoming call following function is called.
-(void)showLocalNotification:(NSNotification *)notification {
NSDictionary *dic = notification.userInfo;
NSString *msg = [dic objectForKey:#"msg"];
NSString *sound = [dic objectForKey:#"sound"];
[[UIApplication sharedApplication] cancelAllLocalNotifications];
UILocalNotification *_localNotification = [[UILocalNotification alloc]init];
//setting the fire dat of the local notification
_localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:1];
//setting the time zone
_localNotification.timeZone = [NSTimeZone defaultTimeZone];
//setting the message to display
_localNotification.alertBody = msg;
//default notification sound
if ([sound length]==0) {
_localNotification.soundName = UILocalNotificationDefaultSoundName;
} else {
_localNotification.alertAction = NSLocalizedString(#"Receive", nil);
_localNotification.soundName = #"myringtone.aif";
}
//displaying the badge number
_localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication]applicationIconBadgeNumber]+1;
//schedule a notification at its specified time with the help of the app delegate
[[UIApplication sharedApplication]scheduleLocalNotification:_localNotification];
}
This function set a scheduleLocal notification to show an alert with two buttons Cancel and Receive which fires after a second.
Now the problem is:
This local notification appears to user only when a background task started as following
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UIApplication* app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
}
But after 10 minutes background task stops. Then local notification does not appear to user though it fires (A log prints after firing)
I did modify the applicationDidEnterBackground function as following to restart background task for long running. But unable.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
expirationHandler = ^{
[app endBackgroundTask:self.bgTask];
self.bgTask = UIBackgroundTaskInvalid;
self.bgTask = [app beginBackgroundTaskWithExpirationHandler:expirationHandler];
}
self.bgTask = [app beginBackgroundTaskWithExpirationHandler:expirationHandler];
}
Now the questions are:
Is there any way which will fire local notification and appear to user when application is in background?
If background task is mandatory, how could be it long run to show local notification to appear user after 10 minutes?
I am using iPhone 3gs, iPhone 4 and iPhone 5.
Try This :
- (void)applicationDidEnterBackground:(UIApplication *)application
{
__block UIBackgroundTaskIdentifier bgTask ;
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
pollingTimer2 = [NSTimer scheduledTimerWithTimeInterval:4.0f target:self selector:#selector(process) userInfo:nil repeats:YES];
}
-(void) process
{
[self didLocalNotification];
}
-(void)didLocalNotification
{
[[UIApplication sharedApplication]cancelAllLocalNotifications];
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
if (localNotification == nil)
{
return;
}
NSLog(#"calling didLocalNotification");
localNotification.applicationIconBadgeNumber =0;
localNotification.alertBody =#"Message!";
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:0];
localNotification.timeZone = [NSTimeZone defaultTimeZone];
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
}
When the application enters into background state, the time used to run in background is not working. Following is the code.
In AppDelegate.h,
#interface AppDelegate : UIResponder <UIApplicationDelegate>
{
BOOL status;
UIBackgroundTaskIdentifier bgTask;
}
In AppDelegate.m
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSAssert(self->bgTask == UIBackgroundTaskInvalid, nil);
bgTask = [application beginBackgroundTaskWithExpirationHandler: ^{
dispatch_async(dispatch_get_main_queue(), ^{
[application endBackgroundTask:self->bgTask];
self->bgTask = UIBackgroundTaskInvalid;
});
}];
dispatch_async(dispatch_get_main_queue(), ^{
if ([application backgroundTimeRemaining] > 1.0) {
// Start background service synchronously
[[vController getInstance] run];
}
[application endBackgroundTask:self->bgTask];
self->bgTask = UIBackgroundTaskInvalid;
});
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
NSAssert(self->bgTask == UIBackgroundTaskInvalid, nil);
bgTask = [application beginBackgroundTaskWithExpirationHandler: ^{
dispatch_async(dispatch_get_main_queue(), ^{
[application endBackgroundTask:self->bgTask];
self->bgTask = UIBackgroundTaskInvalid;
});
}];
dispatch_async(dispatch_get_main_queue(), ^{
if ([application backgroundTimeRemaining] > 1.0) {
// Start background service synchronously
[[vController getInstance] stopbackground];
}
[application endBackgroundTask:self->bgTask];
self->bgTask = UIBackgroundTaskInvalid;
});
}
And in view Controller.h,
#interface vController : UIViewController <AVAudioPlayerDelegate>
-(void) run;
-(void) stopbackground;
-(void) getMessage:(NSTimer*)theTimer;;
+(vController*) getInstance;
#property (nonatomic,retain) NSTimer * timer;
#end
the view controller.m,
#implementation vController
#synthesize timer;
vController *tvc;
- (void)viewDidLoad
{
[super viewDidLoad];
tvc = self;
// Do any additional setup after loading the view, typically from a nib.
}
+ (vController*) getInstance
{
return tvc;
}
- (void)stopbackground
{
timer = [NSTimer scheduledTimerWithTimeInterval:15.0 target:self selector:#selector(getMessage:) userInfo:nil repeats:YES];
}
- (void)run
{
timer = [NSTimer scheduledTimerWithTimeInterval:15.0 target:self selector:#selector(getMessage:) userInfo:nil repeats:YES];
}
- (void) getMessage:(NSTimer*) theTimer
{
NSError *error;
NSString *path = [[NSBundle mainBundle] pathForResource:#"alert" ofType:#"mp3"];
AVAudioPlayer* theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:&error];
if (theAudio == nil) {
NSLog(#"%#", [error description]);
}
NSLog(#"Hi");
theAudio.delegate = self;
theAudio.numberOfLoops = 1;
[theAudio play];
}
- (void) dealloc{
[timer release];
[super dealloc];
}
I am using it on simulator 6.0
Depending on your use case, this may not be possible. Namely, Apple does not let you execute code in the 'background' unless you are performing one of the following tasks:
Apps that play audible content to the user while in the background,
such as a music player app
Apps that keep users informed of their location at all times, such as a navigation app
Apps that support Voice over Internet Protocol (VoIP)
Newsstand apps that need to download and process new content
Apps that receive regular updates from external accessories
Read more at :http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html
By Creating Instance you can Run Background Task in Any View-controller like Below:
// Declare the following in YourViewController.h file.
+ (YourViewController *)getInstance;
- (void)run;
-(void)stopbackground;
// Define the Vollowing in YourViewController.m file.
static YourViewController *instance = NULL;
+(YourViewController *)getInstance {
#synchronized(self) {
if (instance == NULL) {
instance = [[self alloc] init];
}
}
return instance;
}
- (void)run
{
// strat Back ground task
}
-(void)stopbackground
{
// Stop Background task
}
in AppDelegate.h file Declare the Following
UIBackgroundTaskIdentifier bgTask;
in AppDelegate.m file use the Following Methods.
- (void)applicationDidEnterBackground:(UIApplication *)application {
NSLog(#"Application entered background state.");
// bgTask is instance variable
NSAssert(self->bgTask == UIBackgroundTaskInvalid, nil);
bgTask = [application beginBackgroundTaskWithExpirationHandler: ^{
dispatch_async(dispatch_get_main_queue(), ^{
[application endBackgroundTask:self->bgTask];
self->bgTask = UIBackgroundTaskInvalid;
});
}];
dispatch_async(dispatch_get_main_queue(), ^{
if ([application backgroundTimeRemaining] > 1.0) {
// Start background service synchronously
[[YourViewController getInstance] run];
}
[application endBackgroundTask:self->bgTask];
self->bgTask = UIBackgroundTaskInvalid;
});
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
NSLog(#"Application entered background state.");
// bgTask is instance variable
NSAssert(self->bgTask == UIBackgroundTaskInvalid, nil);
bgTask = [application beginBackgroundTaskWithExpirationHandler: ^{
dispatch_async(dispatch_get_main_queue(), ^{
[application endBackgroundTask:self->bgTask];
self->bgTask = UIBackgroundTaskInvalid;
});
}];
dispatch_async(dispatch_get_main_queue(), ^{
if ([application backgroundTimeRemaining] > 1.0) {
// Start background service synchronously
[[YourViewController getInstance] stopbackground];
}
[application endBackgroundTask:self->bgTask];
self->bgTask = UIBackgroundTaskInvalid;
});
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
**Hi every1,
Snapshots of my app are being logged in Cache/Snapshots folder. I just don't need to log these snapshots due to the security concerns.
I have used this below piece of code, which I got this from net to remove the snapshots which are saved :
- (void)applicationDidEnterBackground:(UIApplication *)application {
UIApplication* app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier __block bgTask;
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
if(UIBackgroundTaskInvalid != bgTask) {
// Start the long-running task to kill app after some secs and return immediately.
dispatch_after( dispatch_time(DISPATCH_TIME_NOW, KILL_IN_BACKGROUND_AFTER_SECS * 1e09),
dispatch_get_main_queue(), ^{
if(goingToQuit) exit(0);
[app endBackgroundTask: bgTask];
});
}
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// cancel ongoing background suicide.
goingToQuit = NO;
}
I dont want to log these snapshots, please advice on this.**
I think you are not adding code to delete files :( Please refer my code snippet
- (void) deleteFiles {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self beingBackgroundUpdateTask];
NSError *error = nil;
// dirPath is path to your snapshot directory
NSArray *directoryContents = [fileMgr contentsOfDirectoryAtPath:dirPath error:&error];
if (error == nil) {
for (NSString *path in directoryContents) {
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:path];
BOOL removeSuccess = [fileMgr removeItemAtPath:fullPath error:&error];
if (!removeSuccess) {
// Error handling
...
}
}
} else {
// Error handling
}
// Do something with the result
[self endBackgroundUpdateTask];
});
}
- (void) beingBackgroundUpdateTask {
self.backgroundUpdateTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[self endBackgroundUpdateTask];
}];
}
- (void) endBackgroundUpdateTask {
[[UIApplication sharedApplication] endBackgroundTask: self.backgroundUpdateTask];
self.backgroundUpdateTask = UIBackgroundTaskInvalid;
}
I want to develop app that get current location in background mode of app , and generate according to location particular event ,
So , how can I make app that go in to background and get continues location.
Apple has written a demo app doing exactly what is asked: Breadcrumb
- (CLLocationManager *)locationManager
{
if (locationManager != nil)
return locationManager;
locationManager = [[CLLocationManager alloc] init];
//locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
locationManager.delegate = self;
return locationManager;
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UIApplication* app = [UIApplication sharedApplication];
// Request permission to run in the background. Provide an
// expiration handler in case the task runs long.
NSAssert(bgTask == UIBackgroundTaskInvalid, nil);
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
// Synchronize the cleanup call on the main thread in case
// the task actually finishes at around the same time.
dispatch_async(dispatch_get_main_queue(), ^{
if (bgTask != UIBackgroundTaskInvalid)
{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do the work associated with the task.
// Synchronize the cleanup call on the main thread in case
// the expiration handler is fired at the same time.
dispatch_async(dispatch_get_main_queue(), ^{
if (bgTask != UIBackgroundTaskInvalid)
{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
});
});
}
- (void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation`
{
NSLog(#"location changed");
UIApplication* app = [UIApplication sharedApplication];
NSArray* oldNotifications = [app scheduledLocalNotifications];
// Clear out the old notification before scheduling a new one.
if ([oldNotifications count] > 0)
[app cancelAllLocalNotifications];
// Create a new notification.
UILocalNotification* alarm = [[[UILocalNotification alloc] init] autorelease];
if (alarm)
{
alarm.timeZone = [NSTimeZone defaultTimeZone];
alarm.repeatInterval = 0;
alarm.soundName = #"b.wav";
alarm.alertBody = #"Location changed!";
[app scheduleLocalNotification:alarm];
}
}
I want to play audio in the background when I quit an application, but the following code does not appear to achieve this. What might I be doing wrong?
- (void)applicationDidEnterBackground:(UIApplication *)application
{
printf("hello");
UIApplication *app = [UIApplication sharedApplication];
//beginBackgroundTaskWithExpirationHandler *bgTask;
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{[theAudio play]; [app
endBackgroundTask:bgTask]; bgTask =UIBackgroundTaskInvalid;
NSString *path = [[NSBundle mainBundle] pathForResource:#"Piano"ofType:#"caf"];
theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate = self;
[theAudio play];
}];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
});
// Do the work associated with the task.
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;;
NSLog(#"hello%#",bgTask);
}
An app cannot play sounds in the background unless the audio output was started before the app was put into the background.
You have a wrong order. Your code have to look like so:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
printf("hello");
UIApplication *app = [UIApplication sharedApplication];
//beginBackgroundTaskWithExpirationHandler *bgTask;
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
// A handler to be called shortly before the application’s remaining background time reaches 0. You should use this handler to clean up and mark the end of the background task. Failure to end the task explicitly will result in the termination of the application.
[theAudio pause];
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
});
// Do the work associated with the task.
NSString *path = [[NSBundle mainBundle] pathForResource:#"Piano"ofType:#"caf"];
theAudio=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate = self;
[theAudio play];
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
NSLog(#"hello%#",bgTask);
}