I have an app that imports data on start using Core Data. In this part of the app, I have disabled resuming (multitasking) by calling exit(0) in applicationDidEnterBackground when a flag is set. E.g.:
-(void)applicationDidEnterBackground:(UIApplication *)application {
if (allowResuming==NO){
NSLog(#"Terminating...");
exit(0);
}
}
If I then attempt to 'resume' the app (by pressing its icon) within 11 seconds of having pressed the Home button (and, therefore, exit(0) having been called), the app crashes. This doesn't happen when running through the debugger, but the crash logs suggest that it looks like the app is trying to resume the data import where it left off, which, of course, is not what I want.
Attempting to 'resume' the app again straight after this crash (i.e. within a second) is successful.
If I attempt to 'resume' the app after 11 seconds, it's fine.
I would be really grateful if anyone has any ideas and/or can point me in the right direction here.
I don't think you should be doing exit(0). To disable Multitasking, set the key UIApplicationExitsOnSuspend key in Info.plist to YES. For details, see the section Opting Out of Background Execution at
http://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/CoreApplication/CoreApplication.html#//apple_ref/doc/uid/TP40007072-CH3-SW1.
To discard the partial work done when the app leaves foreground, add a listener for UIApplicationWillResignActiveNotification or UIApplicationDidEnterBackgroundNotification. In the handler method, you could do something like-
[self discardPartialWorkDone];
HTH,
Akshay
You should not use exit(0) like Akshay said. In addition to that Apple will probably reject your App, because Apps which consist of code which interrupt the App like this wont be approved.
Related
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.
I have an app in Xcode which handles sensitive data. I would like to terminate the app / exit forcefully if there is inactivity for 5 mins. Can someone please tell me how to do this?
Thank you!
Click here for a tutorial on how to make a timer. Every action that the user takes, reset the timer. When the 5 minutes are up, you can use exit(0).
However, this method of programatically closing your app is discouraged by Apple, so use it at your own discretion.
Edit: In order to stop the timer, you need to store a pointer to the timer that you create, and then call:
[pointerToTimer invalidate];
pointerToTimer = nil;
Edit 2: An alternative to using exit(0) would be to make a almost blank screen except for some text that states:
You have been inactive for too long. Please exit and restart this application.
Make this screen appear once the timer gets to 5 minutes. Therefore, the user can't do anything on the app but look at the screen, or exit the app.
If you're writing an app to submit to the app store, you can't (according to the guidelines). See details in this note: http://developer.apple.com/library/ios/ipad/#qa/qa1561/_index.html
If you don't care about the store or interface guidelines, it suggests that exit() is available.
I really don't think this can be done, but still my boss wants me to provide a link where it says so. What he wants is to add an 'are you sure you want to exit?' warning when the user presses the home button, and if the user says 'no' the app won't go inactive.
It can't be done, can it?
No, you cannot do this - the application has no say in this. Ask your boss whether he has ever seen a single example of an iOS application that would do this. There isn't ... not one I would bet.
The application can continue to execute some functionality in the background - streaming music, getting location information for example, but no application can block the home button. If you could do this, you could block an application from ever closing.
A) You couldn't technically do this and
B) Apple wouldn't allow it to be released on the App Store if that was the distribution route you were taking
If you look at the methods stubs created by XCode when you create an application delegate
-(void)applicationWillResignActive:(UIApplication *)application
-(void)applicationWillTerminate:(UIApplication *)application
That are filled will comments about how you can use this method to pause tasks, disable timers, throttle down frame rates, save data - there is nothing about being able to delay, query the user with an "Are you sure" message.
This whole idea is rather counter to the user-experience of the iPhone/Pad/Pod-Touch.
From the App Store guidelines (slightly abbreviated):
Apps that alter the behavior of switches on the device will be
rejected
This is a proposed change the behavior of the home button - so would be rejected.
This is possible on a jail broken device, using un-aproved API's. The concept is in multiple violations of apple's usage policy however so you would never, ever, ever get an app attempting to implement this in any way on the official app store. Here's just a few reasons:
You can't alter the functionality of any buttons (including the volume buttons, some camera apps used to use them to take pictures, but they got booted from the store as a result).
You can't interfere with standard user interactions with the device. The home button takes people home, you can't prevent that, or ask for confirmation as that would be interfering with the interaction.
There is no public API to detect actual usage of the home button. As such you would need a private API, and you can not use private API's without explicit permission from Apple, which they would never give due to #1 and #2 above.
I'm sure there's plenty of more reasons, but regardless it would be in direct violation of app store policies as well as iOS human interface guidelines.
You can detect when the app is about to lose focus, has lost focus, or could loose focus (such as a phone call is coming in) but you can not alter the flow (i.e. not allow the app to lose focus).
You can continue to execute code in the background within the backgrounding guidelines and limitations. The backgrounded code could submit a notification to the user that would allow them to switch back into the app... that's about as close as you could get, and expect apple to reject you if it happens every time the app closes...
Already answered by numerous others, but no, you can't do this. When the user presses the home button, your application delegate's applicationWillResignActive is called which disables touch events to the application. Then applicationDidEnterBackground is called, which, per the Apple docs:
Your delegate’s applicationDidEnterBackground: method has
approximately 5 seconds to finish any tasks and return. In practice,
this method should return as quickly as possible. If the method does
not return before time runs out, your application is killed and purged
from memory
You need proof to show your boss that obviously isn't an iOS developer.
Apple Human Interface Guide
That should be all the proof you need. But to be clear, Apple will not allow an app to override the home button in any way. You can surely put action sheets or pop ups to warn before logging out, but once the home button is pressed, you are on notice to give up your memory, you are being shut down.
You might want to look into the Store Demo Mode of IOS. This way you can disbale the Home button and lock the device in the first app you start after booting.
I know I'm too late to answer this question.
But I recently came with the issue which Samssonart had.
The answer given by #iandotkelly is deprecated with iOS5. Now none of delegate method will be used to distinguish between locking the device or sending app to background using Home button.
you can now use applicationState variable to define what action is triggered.
applicationState is an inbuilt id provided by appDelegate.
**
if it returns 2 then, it will identify the Home button is pressed
if it returns 1 then, it will identify the lock hardware button is pressed
**
So, in your case you can check out this condition in **applicationDidEnterBackground** method
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(#"decision >> %d",[[UIApplication sharedApplication] applicationState]);
}
Enjoy Programming!
The best reference I can find is this one. It's not quite explicit, but Apple's Human Interface Guidelines have a couple of headings 'Always Be Prepared to Stop', followed by 'Don't Quite Programmatically', which spell out what the home button does and that you shouldn't be implementing your own quitting strategies.
I know this is an old topic, but I just want to update this answer. In iOS 7 this is not working.
So I use screenbrightness when the app will go to the background to identify difference between the Home and Lock button.
-(void)applicationDidEnterBackground:(UIApplication *)application {
if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateInactive) {
NSLog(#"Sleep button pressed");
} else if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground) {
if ([[UIScreen mainScreen] brightness] > 0.0)
NSLog(#"Home button pressed");
else
NSLog(#"Sleep button pressed");
}
}
I hope this is gonna be of any help for in future for anyone
So I have been doing a lot of reading about the way iOS handles application state notifications, and it looks like they may have created a problem for me in iOS 4.
Before 4.x, I was cleaning out my NSUserDefaults in the - (void)applicationWillTerminate:(UIApplication *)application {} delegate method.
Unfortunately, it does not look like this method is used anymore when the user quits the app from the desktop (pressing the red "-"). Instead the app receives a SIGKIL. Has anyone schemed a way to capture this and do something when the app is terminated (such as clean out the UserDefaults)? I would prefer to not disable the multitasking since that's non-standard behavior. Any help at all would be appreciated. Thanks!
That method will still be sent if iOS ever decides to quit the app. You should probably put the same cleanup code in applicationWillResignActive: if you want it to clean up when moving to the background as well.
However, if you say you want to support multitasking, why are you wiping the default? Shouldn't the user be able to come back to the app exactly as they left it?
By "clean out" do you mean "synchronize to disk"? (i.e. by calling -synchronize)
If so, NSUserDefaults handles this for you automatically, no need to worry about it.
You still need the code in applicationWillTerminate: for those iOS 4 devices that don't support multi-tasking. But you'll also need to call the same code when the app goes into the background (applicationDidEnterBackground:). You might also consider applicationWillResignActive:, but this would get called when a call or an SMS arrives rather than only when it goes into the background.
Is there any way to cause an app to quit instead of going to background when the home button is pressed? For security reasons, it would be better if the app did not run in background but actually closed when home is pushed. This is not for users' security, but rather for company data on the app, so it is not a user's choice. I could not find any way to quit other than forcing an exit, which Apple discourages.
See opting out of background execution in the iphone application programming guide:
"If you do not want your application to remain in the background when it is quit, you can explicitly opt out of the background execution model by adding the UIApplicationExitsOnSuspend key to your application’s Info.plist file and setting its value to YES.
When an application opts out, it cycles between the not running, inactive, and active states and never enters the background or suspended states.
When the user taps the Home button to quit the application, the applicationWillTerminate: method of the application delegate is called and the application has approximately five seconds to clean up and exit before it is terminated and moved back to the not running state."
Just go to info.plist of your project and check "Application does not run in background" to YES.
Unfortunately after trying out everything, I was still not able to see my application exiting on pressing home button. It always went into background even though UIApplicationExitsOnSuspend was YES and of type boolean in plist file and I removed the application from Simulator, restarted Xcode and Simulator and tried everything suggested.
Finally I started debugging the application and found one function which was preventing the application from exiting. The function was fairly simple and was downloading some images from network and was getting called from applicationDidFinishLaunching of appDelegate file. This function was delegating the task of creating network connection and downloading data to some other reusable class where I had the below code:
if(isBackgroundProcessingSupported){
appDelegate.bgTask = [app beginBackgroundTaskWithExpirationHandler:^{}];
[NSURLConnection connectionWithRequest:request delegate:self];
}
So finally it turned out that the above code was responsible for putting the application into background on press of home button. When I commented the above code, my application is exiting instead of going into background.
NOTE: The code was there earlier as initially application was supporting background processing.
Hope this helps someone who is also struggling to find the reason like me.