MPMoviePlayerController getting paused when app enters in background [duplicate] - ios

I'm uisng this code to display a movie:
MPMoviePlayerViewController *mp = [[MPMoviePlayerViewController alloc]
initWithContentURL:movieURL];
mp.moviePlayer.movieSourceType = MPMovieSourceTypeUnknown;
[self presentMoviePlayerViewControllerAnimated:mp]; [mp.moviePlayer play];
The code is working fine. However when the application goes to the background while playing a movie, when the app comes back in the foreground the movieplayer is not displayed. (I see the view of the controller that called presentMoviePlayerViewControllerAnimated:mp
Is it possible when entering the foregound to resume the movie that was playing before the app went to the background?

Have you set the UIBackgroundmode to audio and also there has been problem with playing the video after app enters foreground .Refer this Tutorial on MPMoviePlayerViewController Also you can try using MPMoviePlayerViewController which has options for implementing various notifications .

you can implement notification techniques to handle it. Add a notification in the class where movie player is playing and associate with it a selector. When app goes to background then in the delegate method
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
UIApplication *app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier bgTask = 0;
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
}];
}
write this code.Actually when app goes background it pauses the MPMoviePlayerController so when it is coming to foreground you post the notification which call the method in class where movie controller is implemented and play it again in this method.
-(void)playIntroAnimationAgain
{
[[NSNotificationCenter defaultCenter]removeObserver:self name:NOTIFICATION_PlayAgain_Player object:nil];
[self.moviePlayerController play];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(playIntroAnimationAgain)name:NOTIFICATION_PlayAgain_Player object:nil];
}
It solved my problem.

Related

Bring app to foreground from iPhone lock screen

I have an application an I managed to make a custom remote controller with help of this question on stack overflow.
it works fine but in I want to bring app to foreground by asking the user to unlock the phone, something like apple Musics share button action. Is it possible to ask user to unlock the phone and bring app to foreground to complete an action?
I managed to make it work using local notification, but I think there need to be an alert view or a user interaction with button. Is it possible to make it work without any pop-up?
Here is the code I used to change lock screen controllers button
//App delegate
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
if ([UIApplication instancesRespondToSelector:#selector(registerUserNotificationSettings:)]){
[application registerUserNotificationSettings:[UIUserNotificationSettings
settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|
UIUserNotificationTypeSound categories:nil]];
}
}
// inside viewDidLoad
MPRemoteCommandCenter *rcc = [MPRemoteCommandCenter sharedCommandCenter];
MPFeedbackCommand *likeCommand = [rcc likeCommand];
[likeCommand setEnabled:YES];
[likeCommand setLocalizedTitle:#"I love it"]; // can leave this out for default
[likeCommand addTarget:self action:#selector(likeEvent:)];
MPFeedbackCommand *dislikeCommand = [rcc dislikeCommand];
[dislikeCommand setEnabled:YES];
[dislikeCommand setActive:YES];
[dislikeCommand setLocalizedTitle:#"I hate it"]; // can leave this out for default
[dislikeCommand addTarget:self action:#selector(dislikeEvent:)];
BOOL userPreviouslyIndicatedThatTheyDislikedThisItemAndIStoredThat = YES;
if (userPreviouslyIndicatedThatTheyDislikedThisItemAndIStoredThat) {
[dislikeCommand setActive:YES];
}
//Selectors:
-(void)dislikeEvent: (MPFeedbackCommandEvent *)feedbackEvent
{
//I need to ask user to unlock the phone and bring app to foreground
NSLog(#"Mark the item disliked");
}
-(void)likeEvent: (MPFeedbackCommandEvent *)feedbackEvent
{
//I need to ask user to unlock the phone and bring app to foreground
NSLog(#"Mark the item liked");
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:0];
notification.alertBody = #"This is local notification!";
notification.timeZone = [NSTimeZone defaultTimeZone];
notification.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
I suppose these delegate methods in the appdelegate.h would be helpful.
I think you could use the last one, "application did become active."
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
OR
By using notification center you can perform any actions in particular classes, i have used will enter foreground. There are different options available as per users requirements.
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(appReturnToForeground) name:UIApplicationWillEnterForegroundNotification object:nil];
}
- (void)appReturnToForeground {
// Your code...What you want to perform.
}

How to call method/code when app is paused in iOS

As the title reads; I am currently playing a sound file on loop using this code:
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"smoothjazz" ofType:#".mp3"];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath:soundFilePath])
{
// Your code to play the sound file
[player setVolume:1.0];
player.numberOfLoops = 5; //infinite
[player play];
}
However, the music keeps playing when you pause the app (hit the home button). How can I call [player setVolume:0.0] when the app is paused and [player setVolume:1.0] when it is resumed?
All help appreciated.
You can use NSNotificationCenter to listen to the UIApplicationWillResignActiveNotification and UIApplicationDidBecomeActiveNotification notifications in your view controller (or whatever object your above code is in) and the pause/resume playing you sounds there.
You should probably not set the volume on your player. It would probably be better to call
[player pause] and [player play]
There is a protocol that handles state change: UIApplicationDelegate. The ones you are interested in right now are willResignActive and didBecomeActive.
Note that these are not didEnterBackground and willEnterForeground. The difference is the former will get hit when apps takeover, such as Siri, and the latter will not.
You can implement this protocol in your audio manager class and set the volume at that point, like so:
- (void)applicationWillResignActive:(UIApplication *)application {
self.currentVolume = self.player.volume;
self.player.volume = 0;
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
self.player.volume = self.currentVolume;
}
There may be no need to store the current volume, but designing on it to be used like that now will allow you to implement that in the future.
You should consider whether or not you want to mute the player or pause it. I'm sure you have, but a general better practice here would be to pause it rather that mute it, but that's not something that applies to every situation.
Additionally, you should know that some programmers are of the school of thought that only the AppDelegate should implement the UIApplicationDelegate protocol. There's some good arguments for it, and personally, I'm not really decided on what's best practice on that, but if you want to follow that, then you can either set up a protocol to delegate these in your AppDelegate and have your audio manager implement that delegate or you can use NSNotificationCenter to broadcast the event to any listeners - so, your audio manager in this case. Of the two, I would say using notifications is a cleaner way to handle it (delegating to delegates is a bit silly to me), but they also can get messy if you're not careful.
Here's the code I added to the viewDidLoad to call the method on the app pausing:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(muteMusic)
name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(activateMusic)
name:UIApplicationDidBecomeActiveNotification object:nil];
Then, of course, my two methods:
- (void) muteMusic {
[player pause];
}
- (void) activateMusic {
[player play];
}
Enjoy!

pause player when going to background and resume when app returns to foreground ios

When playing a video in an iOs app I need it to pause when the app is sent to background and resume when the app returns from background.
- (void)onApplicationDidBecomeActive:(NSNotification *)notif
{
NSLog(#"player: app did become active...");
[self.videoPlayer play];
}
- (void)onApplicationDidEnterBackground:(NSNotification *)notif
{
NSLog(#"player: app did enter background...");
[self.videoPlayer pause];
[self.videoPlayer setFullscreen:NO];
}
On iOS7 this works ok but io iOs8 it seems that another player is created underneath the current one. (self.videoPlayer is a MPMoviePlayerController)
Why is this?

Stop location updates when app terminate

I'm developing an app which sends notifications when you are nearby of promoted places.
My problem is when I go to background and then I quit the app, I don't want the location services working when the app doesn't work (but I want them to work in background).
I saw only 3 apps which close the gps when the app is closed and I want to know how they did that, Facebook, Google Maps and Apple Maps, not Foursquare, not FieldTrips...
Thank you everybody.
you can add an observer for UIApplicationWillTerminateNotification where you start locationManager and than stop location updates
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationWillTerminate:)
name:UIApplicationWillTerminateNotification
object:nil];
method to perform when you receive the notification
- (void)applicationWillTerminate:(NSNotification *)notification {
//stop location updates
}
I found the correct answer to my question becouse of #GuyS second post:
Adding that in your AppDelegate.m applicationDidEnterBackground
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UIApplication *app = [UIApplication sharedApplication];
if ([app respondsToSelector:#selector(beginBackgroundTaskWithExpirationHandler:)]) {
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;
}
});
}];
}
}
And declaring that variable:
UIBackgroundTaskIdentifier bgTask;
After that you only have to stop your location services in applicationWillTerminate...
Thank you for your replies.
The solution provided by #GuyS in this topic should work. I'm getting the UIApplicationWillTerminateNotification in case the app is in background and then I close it by swiping up the snapshot. Please check whether you work correctly with NSNotificationCenter (especially adding and removing notification). Plus, please check the object you subscribed on the notification is alive when the app is in background.
Another similar solution is to place the code that disables GPS in appropriate UIApplicationDelegate callback in your AppDelegate method.
- (void)applicationWillTerminate:(UIApplication *)application {
//stop location updates
}

AVCapturesession handling after returning from background

I am implementing a VideoRecorder using the AVCaptureSession.
I am starting AVCaptureSession at viewWillAppear and tearing it down at viewWillDisappear on recommendation of this question AVCaptureSession fails when returning from background
.
Now when the Video is Recording and the app goes to background I want to stop recording and pause the capture session. But each time the app comes to foreground at this point I get one of the following
Capture Session is not paused but recording and the Preview Layer keeps updating
Capture Session provides Preview Layer with black-screen at this point app may or may not crash.
Any suggestions on handling the AVCaptureSession at this point. I would like to just show the last frame recorded on the previewLayer, once recording stops.
I have encountered a similar situation and in my experience I have found that viewWillDisappear: doesn't get called. I'm really not sure why, but I solved it by subscribing for notifications when the app goes inactive. Here's an example:
In viewWillAppear:
// Detect this for ending recording
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(appInactive:) name:UIApplicationWillResignActiveNotification object:[UIApplication sharedApplication]];
And the appropriate callback method:
- (void)appInactive:(NSNotification *)notification {
NSLog(#"App going inactive, stopping recording...");
taskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^{
[[UIApplication sharedApplication] endBackgroundTask:taskId];
taskId = UIBackgroundTaskInvalid;
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
question.prepTimeRemaining = [prepEndTime timeIntervalSinceNow];
// Stop camera stuff
if (recording)
[self stopRecording]; // Method to handle shutting down the session, any other cleanup, etc.
// End task
[[UIApplication sharedApplication] endBackgroundTask:taskId];
taskId = UIBackgroundTaskInvalid;
});
}
In viewWillDisappear:
[[NSNotificationCenter defaultCenter] removeObserver:self];
I immediately move to the next view when I detect this, so I'm not sure what it leaves behind on the preview layer, but I suspect it would do what you want. Hope this helps!
This is late but I was experiencing some of the same. In order to get around the problem you first have to realize ViewWillAppear and ViewWillDisappear are strictly for in app transitions from one View Controller to another. They don't work for foreground to background and back again transitions. I used a similar fix above:
//application became active
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationEnteredForeground:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
//application went into background
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationBecameActive:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
In the selector methods just stop and start your camera session and as the other stackoverflow post suggest, it would be a good idea to lazily instantiate your avcapturesession so that your app is memory conservative

Resources