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];
}
}
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];
}
I would like my app to monitor my accelerometer for an infinite time (even in the background). When it reaches a certain amount, I would like to deliver a local notification. This is exactly the same functionality as the 'Sleep Cycle' app has.
But how did they do this? When I use the beginBackgroundTaskWithExpirationHandler function, it isn't working anymore after 10 minutes. Adding UIBackgroundModes doesn't help at all.
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
_motionManager = [[CMMotionManager alloc] init];
_motionManager.accelerometerUpdateInterval = 1;
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[_motionManager startAccelerometerUpdatesToQueue:queue withHandler:^(CMAccelerometerData *accelerometerData, NSError *error)
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(#"%#",accelerometerData);
if(accelerometerData.acceleration.x > 0.5){
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
return;
localNotif.fireDate = [NSDate date];
localNotif.timeZone = [NSTimeZone defaultTimeZone];
localNotif.alertBody = #"Wake up!";
localNotif.alertAction = #"wake";
localNotif.soundName = UILocalNotificationDefaultSoundName;
localNotif.applicationIconBadgeNumber = 4;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
});
}];
To run your app infinitely in background, you need to provide the UIBackgroundModes value in Info.plist file.
https://developer.apple.com/library/ios/documentation/iphone/conceptual/iphoneosprogrammingguide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html#//apple_ref/doc/uid/TP40007072-CH4-SW20
Issue is, i put a date picker programmatically. In date picker i just used to display time from 1mins to 23 hours. User is supposed to set the time in the picker, and set up the notification.
Now,i get notification in background but only one time.I have to repeat time until timer will not stop.
I found too many links and source but not able to solve this issue
My Code:
In Appdelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
application.applicationIconBadgeNumber = 0;
//------ Handle launching from a notification-------
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
self.localNotification =[launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (self.localNotification)
{
application.applicationIconBadgeNumber = self.localNotification.applicationIconBadgeNumber-1;
NSLog(#"badge number: %d", application.applicationIconBadgeNumber);
[self playSoundWithNotification:self.localNotification];
}
else
{
[[UIApplication sharedApplication]cancelAllLocalNotifications];
}
}
didenterinbackground:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(#"Application entered background state.");
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(), ^{
while ([application backgroundTimeRemaining] > 1.0)
{
NSString *str_friend = #"Hello,";
if (str_friend)
{
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif)
{
localNotif.alertBody = [NSString stringWithFormat:
NSLocalizedString(#"%# has a message for you.", nil), str_friend];
localNotif.alertAction = NSLocalizedString(#"Read Msg", nil);
localNotif.soundName = #"alarmsound.caf";
//localNotif.soundName =[NSString stringWithFormat:#"%#.mp3",str_Alarm];
localNotif.applicationIconBadgeNumber = 1;
[application presentLocalNotificationNow:localNotif];
NSLog(#"sound: %#, alertAction: %#, alerBody: %#",localNotif.soundName, localNotif.alertAction, localNotif.alertBody);
str_friend = nil;
break;
}
}
}
[application endBackgroundTask:self->bgTask];
self->bgTask = UIBackgroundTaskInvalid;
});
}
-
(void)playSoundWithNotification:(UILocalNotification *)notification
{
notification.soundName=[NSString stringWithFormat:#"%#.mp3",str_Alarm];
NSLog(#"soundname: %#",notification.soundName);
}
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif
{
testDate=notif.fireDate;
NSLog(#"DATE IS: %#, %#",testDate, notif.fireDate);
// Handle the notificaton when the app is running
NSLog(#"Recieved Notification %#",notif);
[self playSoundWithNotification:notif];
[self _showAlert:[NSString stringWithFormat:#"%#",str_Motivation] withTitle:#"Daily Achiever"];
}
- (void) _showAlert:(NSString*)pushmessage withTitle:(NSString*)title
{
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:title message:pushmessage delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
if (alertView)
{
}
}
in myviewcontroller:
-(void)insert:(NSDate *)fire
{
appDelegate=(AppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.localNotification = [[UILocalNotification alloc] init];
NSLog(#"localNotification %#", appDelegate.localNotification);
if (appDelegate.localNotification == nil)
return;
appDelegate.localNotification.fireDate = fire;
appDelegate.localNotification.timeZone = [NSTimeZone defaultTimeZone];
appDelegate.localNotification.alertBody = appDelegate.str_Motivation;
appDelegate.localNotification.alertAction = #"View";
appDelegate.localNotification.soundName = [NSString stringWithFormat:#"%#.mp3",appDelegate.str_Alarm];
appDelegate.localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber]+1;
NSLog(#"localNotification.alertBody %#", appDelegate.localNotification.alertBody);
NSLog(#"localNotification.soundName %#",appDelegate.localNotification.soundName);
[[UIApplication sharedApplication] scheduleLocalNotification:appDelegate.localNotification];
}
Please Help.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
......
......
if (localNotif)
{
localNotif.alertBody = [NSString stringWithFormat:
NSLocalizedString(#"%# has a message for you.", nil), str_friend];
localNotif.alertAction = NSLocalizedString(#"Read Msg", nil);
localNotif.soundName = #"alarmsound.caf";
localNotif.applicationIconBadgeNumber = 1;
[localNotif setRepeatInterval:NSMinuteCalendarUnit];
[application presentLocalNotificationNow:localNotif];
str_friend = nil;
break;
}
}
I got solution.
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;
}