i establish a connection between two iOS devices with GameKit and GKMatch for a synchronous game. When one player enter the background the connection will disconnect. How can I avoid this behavior? Is it possible to keep the connection via GKMatch alive while one user did suspend the app to the background?
According to Apple's documentation:
As soon as your game moves to the background, the value of the local player object’s authenticated property becomes and remains invalid until your game moves back to the foreground. You cannot read the value to determine if the player is still authenticated until Game Kit reauthenticates the player and calls your authentication handler. Your game must act as though there is not an authenticated player until your completion handler is called. Once your handler is called, value stored in the authenticated property is valid again.
Source: Game Center Programming Guide, pg. 39.
Unless your App employs VOIP or special circumstances apply, you shouldn't really be keeping a network connection open in the background. (If you are interested though, check out this SO question for a hacker-ish way of going about that).
As your player authentication is invalidated on entering the background, another device (if it does manage to receive network data from the background App) will not (reliably) know which GKPlayer sent the information.
So while Apple don't come out and say it explicitly, all Game Center features should normally be cancelled when the Application enters the background, and resumed once the player is re-authenticated upon relaunch.
As a side note, when an App withdraws to the background it is (usually, depending on background tasks) deemed "eligible for suspension". This is one reason there are such restrictions on multitasking execution - your App could be killed at any moment to free memory and you don't really want a heavy duty data transfer going on when that happens!
See TN227 if you'd like to know more about networking and multitasking.
EDIT: An alternate method:
While it is not possible to keep a GKMatch alive while an App is running in the background, an alternative way to emulate this behaviour would be to save game state to your own server. Ask the user to interact with some UI (press a button maybe) before she/he leaves the game, which saves the current game state to your own server and notifies the other player that you are about to leave the game. Upon relaunch, query your server to see if you have any saved games, and if so, load the game state and send a notification to the other player. This doesn't strictly maintain the same game, but is one way of approximating the behaviour you're after.
This is not possible
you can do like when one player enter in background
in this event
- (void) applicationDidEnterBackground:(UIApplication *)application { }
send the message to the second player in packet data that first player goes in background
then in
- (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context;
{
}
when perticuler that data get stop your application and pop to previous view
Related
Our app would like to access accelerometer data in background. A possible way to achieve is to use Core Motion for accelerometer readings -
with
CLLocationManager* locationManager;
CMMotionManager* motionManager;
...
[motionManager startAccelerometerUpdatesToQueue: ... withHandler: ...]
which works fine on the foreground, but the only way I've found to receive the updates in background is to set the app to allow using Location in background, and call
[locationManager startUpdatingLocation]
in -applicationWillResignActive:
The problem is, when I call startUpdatingLocation that a window pops up with text Turn On Location Services to Allow "app" to Determine Your Location.
But of course, I receive accelerometer readings regardless of whether Location Services are enabled, but the popup is annoying and will probably confuse users.
Is getting accelerometer data in the background somewhat tied to attempting to receive location updates?
You can use startAccelerometerUpdatesToQueue in background, the only thing you need to meet — use any background mode to make you app running in the background (location updates (your case), playback, VoIP or BT4 central).
I have a quiz application in which the duration of each question is 20 sec. It works fine, but in case, if a user gets a call while playing, I want to pause the application & set it in background.
Does anyone have any idea?
It depends on the implementation of your app but, broadly, your application should stop any running timers, pause the game, pause any sound playback, etc. in the applicationWillResignActive: method.
When the call is finished, your app is invoked again and the applicationDidBecomeActive: method is called. You should resume timers, sound playback, etc. from that method. If it's a game, you should not resume it automatically; keep it paused and wait for the user to resume it manually to comply with Apple's UX guidelines.
When a call comes in, your application is suspended.
And you'll know this is happening because your "UIApplicationDelegate" will get a message of "applicationWillResignActive:". When it comes back, you can start up where you left off or you can bring up a new question or whatever you want to do, it's up to how you decide to implement your quiz app.
When user gets a phone call in iphone application automatically goes into applicationDidEnterBackground state.for example if you are working on radio app then radio automatically get off when user get any call after call ended application comes into below method(appDelegate.m)
(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.
}
I have an app, that will keep track of everything the user do in the iPod app. To do this, I added few observers to NSNotificationCenter, like MPMusicPlayerControllerNowPlayingItemDidChangeNotification. But my problem is, I only get those notifications when my app is in the foreground, if its in the background, the system add the notification to a queue, and then the next time my app becomes active it delivers it to me. I have no interest in this queue, since I want to receive real-time notifications.
Is there any way for me to get those notifications even if my app is in suspended state? I want to run just 3 lines of code everytime I get this NowPlayingItemDidChange notifications for example.
Here is where I add the observer.
MPMusicPlayerController *iPodMediaPlayer = [MPMusicPlayerController iPodMusicPlayer];
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver: self selector: #selector(handle_NowPlayingItemChanged:) name:MPMusicPlayerControllerNowPlayingItemDidChangeNotification
object:iPodMediaPlayer];
[iPodMediaPlayer beginGeneratingPlaybackNotifications];
Also, if I add another kind of object to the observer instead of iPodMediaPlayer, the observer won't call the method.
Thanks a lot,
Abras
iOS applications are suspended when they are not in the foreground. There are three exceptions to this rule. You can have code execute in the background if your application is
a) Playing audio. This means the application itself is actually generating audio. My understanding is that the MPMediaPlayerController iPodMusicPlayer object only controls the playback of the external iPod process, rather than playing audio from the app itself. Perhaps you could have some success if you called applicationMusicPlayer instead of iPodMusicPlayer and set the appropriate background flags in your applications Info.plist. This seems like the most legitimate way to get your application to work, but you wouldn't be able to control iPod playback from the iPod app, only your app and the system audio controls.
b) Get your app to monitor the location. If the app is using the GPS it can continue to execute in the background. Downside to this is that the GPS will drain battery, and users might be creeped out that you're requesting their location.
c) Ask UIApplication for extra time. If you use UIApplication's beginBackgroundTask method, your application will continue to run for a finite amount of time in the background. If your users are going to come into your application once every ten minutes or so, this could work as well.
Hope that helps.
Multitasking in iOS is currently a very restricted one. You may start a background task using beginBackgroundTaskWithExpirationHandler: method (of an UIApplication object), but it is intended to finish a finite-length task before going suspended. All background tasks may expire (and get terminated) before it finishes its job. You can check how much longer your application can run by checking backgroundTimeRemaining property of the application object.
As I explained here iOS receive Media Player Notifications when app is in background, there seems no way to get notifications from iPodMusicPlayer.
About Omar Raul Qazi answer:
a) i tried and I had no success. The music kept going down when pressing home button. I think this background flag only works for normal AudioSessions and not for MPMusicPlayer...
b) I am not sure this would work and I don't think Apple would like it when looking for approval
c) You can run in background only synchronous task. You cannot wait there for a notification. Am I wrong?
I have an alarm clock app which works on a timer. When the alarm is meant to go off and the screen is switched off, it should start playing audio from AVAudioPlayer, but it doesn't. Then when i turn the screen back on, i can see that the rest of the code fired as expected (a stop button is now on the screen). How do i get the AVAudioPlayer to play when the screen is turned off?
Is there any way for me to detect that the screen is turned off?
#zoul is correct that using the default audio session category will result in sound form your app being disabled when the user locks the screen. See the Audio Session Programming Guide for direction on which audio session category you should choose.
However, even once your audio session category is set correctly, you'll have another issue to tackle. When the screen is switched off, your application gets suspended per Apple's documentation here: Executing Code in the Background. This means that when the user locks their phone or switches to a different app, your app will stop running and stay in a freeze-dried (task-suspended) state until the user activates your app again. At that point, your app resumes execution as if nothing happened. That's why it appears that your app has continued to function when you unlock the screen.
For alarm behavior, you'll probably want to schedule the delivery of a local notification. A local notification will ensure that the system provides your alert to the user at the time you request, and allows the user to activate your app. See Scheduling the Delivery of Local Notifications for details on how to accomplish this.
Maybe you have the wrong audio category? See the documentation for AVAudioSession, especially the audio category settings.
My app uses NSTimer and it appears that NSTimer doesn't fire when the iPhone goes into the stand-by mode (either by pressing the hardware button or by the idle timer).
When I activate the iPhone again, my app is still in the foreground. What happens to third party apps when the iPhone is the stand-by mode?
Although it's not evident here, I believe the original poster did find an answer to his question by starting a thread (available here) in the iPhone Developer Forums (which I eventually had to find myself because the information wasn't shared here).
In case someone else has the same question and finds the page in the future, here's a helpful response that was posted by someone on the Apple forum called "eskimo1" (which I have edited slightly such that it is easier to read without having the context provided by the entire original thread):
Regarding iPhone app status terminology, "active" does not mean "awake", it means "attached to the GUI". Think of it being analogous to "frontmost" in Mac OS X. When you lock the device your app deactivates but the device may or may not go to sleep
iPhone OS rarely sleeps if the device is connected to main power (i.e., via USB). It can sleep if running on battery, however.
A short time after the screen is locked (20 seconds according to Oliver Drobnik), the device sleeps. This is like closing the lid on your laptop; all activity on the main CPU halts.
This does not happen if the device is playing audio in the right audio session. See DTS Q&A QA1626 "Audio Session - Ensuring audio playback continues when screen is locked" for details.
Note that the idleTimerDisabled property (which can be turned on to prevent the screen from turning off while the app is running) is about locking the screen after user inactivity. It's not directly related to system sleep (it's indirectly related in that the system may sleep shortly after it's locked).
See Application Interruptions in the iPhone OS Programming Guide, especially the applicationWillResignActive and applicationDidBecomeActive events. (The whole guide is certainly worth reading.) When You ignore the events, the timer seems to go on for a while and then stops. Sounds logical, the application could easily drain the battery if kept running. And what exactly happens to the application? I guess it simply does not get any CPU time – it freezes and only thaws when You turn the machine back “on.”
My first advice is do not disable the idle timer, that is just a hack. If you want to keep a timer alive during UI events run the timer on the current run loop using NSCommonModes:
// create timer and add it to the current run loop using common modes
self.timer = [NSTimer timerWithTimeInterval:.1 target:self selector:#selector(handleTimer) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
I used the information on this post for a small sample that I was building. This is the code that I used when I initiated the playback to prevent the audio from stopping:
AudioSession.Category = AudioSessionCategory.MediaPlayback;
And when the application is done with the playback to reset to the original value:
AudioSession.Category = AudioSessionCategory.SoloAmbientSound;
The full sample is here:
http://github.com/migueldeicaza/monotouch-samples/tree/master/StreamingAudio/
I was faced with this issue recently in an app I am working on that uses several timers and plays some audio prompts and made two relatively simple changes:
In the AppDelegate I implemented the following methods and there mere presence allows the app to continue when the screen is locked
// this receives the notification when the device is locked
- (void)applicationWillResignActive:(UIApplication *)application
{
}
// this receives the notification that the application is about to become active again
- (void)applicationWillBecomeActive:(NSNotification *)aNotification
{
}
references: UIApplicationDelegate Protocol Reference & NSApplication Class Reference in the API doc (accessible via Xcode, just search for applicationWillBecomeActive).
Made the main viewcontroller class an AVAudioPlayerDelegate and used this code from Apple's "AddMusic" sample to make the audio alerts the app played mix nicely into the iPod audio etc...
I just dropped this code into a method that is called during viewDidLoad. If this interests you, you fall into the "who should read this doc" category for this: Audio Session Programming Guide
// Registers this class as the delegate of the audio session.
[[AVAudioSession sharedInstance] setDelegate: self];
// The AmbientSound category allows application audio to mix with Media Player
// audio. The category also indicates that application audio should stop playing
// if the Ring/Siilent switch is set to "silent" or the screen locks.
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryAmbient error: nil];
// Activates the audio session.
NSError *activationError = nil;
[[AVAudioSession sharedInstance] setActive: YES error: &activationError];
I believe your application should run normally when suspended. (think Pandora Radio)
Check to see if your timer is being deallocated due to your view being hidden or some other event occurring.