I have a application that periodically (via an NSTimer) asks for the users location using locationManager:startUpdatingLocation I want the locationManager to run in the background so have entered "UIBackgroundModes = location" in the info.plist file.
My question is I am not seeing the results I expected, am I right in thinking that when I press the home button the application delegate calls "applicationDidEnterBackground" but although locationManager is allowed to continue my NSTimer is getting suspended (and as a consequence its not calling startUpdatingLocation to periodically query the devices position). Any ideas / solutions would be much appreciated ...
Gary.
All NSTimers are invalidated when entering the background. You need check via the CLLocationManager for any changes.
Just keep the startUpdateLocation running, you delegate will receive any major changes of the location.
When running in the background, you will only receive location changes based on cell towers.
If you read the documentation for -applicationDidEnterBackground: you'll find that yes, your timers are invalidated. Furthermore, the iOS Application Programming Guide tells you exactly how to track location from the background.
Related
I am new to iPhone development, i am creating a location based app. i have searched lot related to location and came to knew that use one object ( singleton pattern ) of CLLocationManager through out app, in my app i have to update user's location to server using web service,
UPDATE
as discussion with Umer i came to knew that i can use one object in appdelegate of CLLocationManager and implement delegate methods in that, and update user location to server in app delegate ,
So, is it good to do in appDelegate ??
please help.
Your locationservices will run both in foreground and background, but to allow it to run in background (when the app is open and minimized), you need to declare a special background mode in your projects "Plist" file, if I'm not wrong.
The method didUpdateToLocation will give you updates every time there is a significant movement, which you can define and adjust through various settings, such as CLLocationAccuracy (locationManager.desiredAccuracy and locationManager.distanceFilter).
Depending on what desired accuracy you ask, battery main drain quicker or not.
I don't understand what you mean with "web service". These are not web-related, they're native functionalities of iOS.
You can just call the delegate method of locationManager StartUpdatingLocation when user moves to significant distance & also call the web-service for updating User's Location.
Both Task are done in Background mode.
UPDATED ANSWER
SOURCE CODE
I am using GeoFencing to set a region and perform some task when user Enters or Leaves the region. Bt it is not working for me, i am using gollowing code
CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(some values,some values);
CLRegion *region = [[CLRegion alloc]initCircularRegionWithCenter:coord radius:15.0 identifier:#"SF"];
[locationManager startMonitoringForRegion:region desiredAccuracy:kCLLocationAccuracyBest];
But None of the delegates didEnterRegion and didExitRegion being called when i close the application and the app is monitoring and i move away from that region or enter.
You define a radius of 15m. That is too small. First, try with 50m or more. Look at the map app, if you really have entered that region.
Furthermore, I hope you meant "send to background", instead of closing.
make sure you have set your app to be allowed to run in background? (via plist)
Update:
Finally it turned out that you terminated the application. Then of course you will not get any loctaion events anymore.
Solution:
Don't terminate it via double click on home button follwed by selecting the white cross, simply close it with one click on home button, then it has chance to run in background.
Update2:
Even when the app was terminated, ios relaunches it when it has registered to the location monitoring service:
from CllLocationManager Class Reference
If you start this service and your application is subsequently
terminated, the system automatically relaunches the application into
the background if a new event arrive...
Add CLLocationManagerDelegate in header file.
make sure u added
locationManager.delegate = self;
try increasing the radius and check.
First of all increase the radius you are giving for that particular location and check again if it does not work then by following some easy steps provided in this tutorial you can easily implement Geo-Fencing in your app.
Reference: Apple Documentation
You define a radius of 15m. That is too small. First, try with 50m or more. Look at the map app, if you really have entered that region.
Furthermore, I hope you meant "send to background", instead of closing.
make sure you have set your app to be allowed to run in background? (via plist)
I am building a word game and I want to hide the board when application is suspended?
the code looks fine however it givs a strange behaviour!!,
when I suspend the app nothing will happen but when i resume the application then the board will hide!!
local onSystem = function( event )
if event.type == "applicationSuspend" then
print("suspend")
board_group.alpha = 0
end
end
Runtime:addEventListener( "system", onSystem )
Note: you might wonder how do I know how the application looks when suspended?
the answer is: by pressing the home button twice.
example
SpellTower in normal state
https://dzwonsemrish7.cloudfront.net/items/430k0c0b0y0b413d0b42/Image%202012.11.12%208:08:24%20AM.png?v=4822f549
SpellTower after pressing the home button twice
https://dzwonsemrish7.cloudfront.net/items/280a1y0r2U3W321y1B2z/Image%202012.11.12%208:08:31%20AM.png?v=09c37567
you can see how they are hiding the letters, this is exactly what I want to do for my game, the only difference is i am using Corona SDK
When you do board_group.alpha = 0 you only has set a variable, the result will only take effect after a screen update.
But since the application is suspended... it won't update! So, changing any graphics on applicationSuspend don't work.
I believe the reason is because the application is not considered as suspended. In normal objective c programming it means that applicationWillResignActive is called when the user double clicks on the home button. So what you want to do is to add that code for this part.
Here is a flow of events:
http://www.cocoanetics.com/2010/07/understanding-ios-4-backgrounding-and-delegate-messaging/
Corona seems to have these events:
"applicationStart" occurs when the application is launched and all code
in main.lua is executed.
"applicationExit" occurs when the user quits the application.
"applicationSuspend" occurs when the device needs to suspend the application such as during a phone call or if the phone goes to sleep
from inactivity. In the simulator, this corresponds to the simulator
running in the background. During suspension, no events (not even
enterFrame events) are sent to the application while suspended, so if
you have code that depends on time, you should account for the time
lost to an application being suspended.
"applicationResume" occurs when the application resumes after a suspend. On the phone, this occurs if the application was suspended
because of a phone call. On the simulator, this occurs when the simulator was in the background and now is the foreground application.
So my guess is that you have to implement it outside of the corona API.
According to the corona documents you can implement them in the delegate:
You can intercept UIApplicationDelegate events via your implementation
of the CoronaDelegate protocol.
This protocol conforms to the UIApplicationDelegate protocol. Corona's
internal delegate will call your protocol's method if it is
implemented.
Please keep in mind the following:
Methods that Apple has deprecated will be ignored.
In most cases, your class' version will be invoked after Corona's corresponding version of the UIApplicationDelegate method. There is one situation in which your version will be called before.
In situations where the app is about to suspend or go to the background, your method will be called before Corona's version, e.g.
applicationWillResignActive: and applicationDidEnterBackground:.
http://docs.coronalabs.com/native/enterprise/ios/CoronaDelegate.html
But this is just a guess. Hope it helps!
Edit:
I was thinking, something really simple you could do is catch it outside and present a "pause" screen, then just hide it when the application enters foreground.
So if you can't do that (for now), one other option is to save application state when the application is about to terminate, and then set UIApplicationExitsOnSuspend = true in your plist file. This will cause the application to exit instead of suspending, which will avoid any screenshots, effectively "hiding" the board, etc. The downfall is, the app will have to read the session state when it launches again... this is only useful if your application can be designed to actually exit without losing your state, and is quite honestly, a little extreme. That said, it may be the only way to effectively do what you're trying to do.
Other ideas would be to see if you can add a large black layer to the screen, even though the application is suspending; perhaps this will somehow trigger an internal screen update by natively setting setNeedsDisplay. Also, instead of modifying the alpha, you might consider temporarily removing all of your layers and see if that has a similar effect.
My game made using cocos2d crashes on iOS5 after resuming from the background when left for a while. I want to know what the standard/best practice is, on handling an app that is sent to the background. Do I terminate it after a certain time? I see some games pull up a loading screen when you resume it after a long time but when you resume it immediately it goes straight to the game. What are they loading when they resume?
Any pointers in the right direction would be much appreciated.
Thanks
AC
You can opt out of background execution by adding UIApplicationExitsOnSuspend to your Info.plist.
Other than that it really is your job to ensure that your app doesn't crash when it resumes execution. You have to understand that your application basically enters a suspended state. That means it should unload all unneeded resources, otherwise the system may terminate your app's process.
In your app delegate you should respond to the applicationDidBecomeActive message and respond accordingly so that your app is able to resume execution without any issues. This can include loading any unloaded assets and checking if system settings (ie. locale, Game Center user, etc.) have changed.
You can also register a didBecomeActive UINotification so that any class in your app gets notified when the app should resume.
When my iPhone app resigns active status, the sharedAccelerometer singleton instance of UIAccelerometer stops sending accelerometer:didAccelerate: messages to my delegate.
Is it at all possible to continue receiving those messages, similarly to how the CLLocationManagerDelegate continues to receive updates when the app is inactive?
I would prefer not to have to disable the idleTimer altogether if it can be helped.
No, not in the most recent available form of the iPhone SDK at least.
I would say that it is possible since this app is on the AppStore:
However, since you move differently in
bed during the different phases, the
Sleep Cycle alarm clock is able to use
the accelerometer in your iPhone to
monitor your movement and determine
which sleep phase you are in.
I can't believe it has to run all night with the screen turned on. EDIT: looks like it has to! :P
So they haven't got around that issue either. More chances that you can't achieve it then...
Have you read the documentation of the UIAccelerometer, does it mention anything there? If it just stops sending acceleration events there is not much you can do.
I would however try to set the accelerometer delegate again to my class when my app has lost focus (when the phone got locked). You can get that notification (lost focus notification) from the UIApplication. Try that just in case the accelerometer's delegate gets set to nil when the app loses focus.