18

I am using Avplayer to show video clips and when i go back (app in background) video stop. How can i keep playing the video?

I have search about background task & background thread ,IOS only support music in background (Not video) http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html

here is some discussion about play video in background

1) https://discussions.apple.com/thread/2799090?start=0&tstart=0

2) http://www.cocoawithlove.com/2011/04/background-audio-through-ios-movie.html

But there are many apps in AppStore, that play video in Background like

Swift Player : https://itunes.apple.com/us/app/swift-player-speed-up-video/id545216639?mt=8&ign-mpt=uo%3D2

SpeedUpTV : https://itunes.apple.com/ua/app/speeduptv/id386986953?mt=8

Vishal Khatri
  • 954
  • 2
  • 12
  • 32

8 Answers8

13

This method supports all the possibilities:

  • Screen locked by the user;
  • List item
  • Home button pressed;

As long as you have an instance of AVPlayer running iOS prevents auto lock of the device.

First you need to configure the application to support audio background from the Info.plist file adding in the UIBackgroundModes array the audio element.

Then put in your AppDelegate.m into

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions:

these methods

[[AVAudioSession sharedInstance] setDelegate: self];    
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];

and #import < AVFoundation/AVFoundation.h >

Then in your view controller that controls AVPlayer

-(void)viewDidAppear:(BOOL)animated
{
  [super viewDidAppear:animated];
  [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
  [self becomeFirstResponder];
}

and

- (void)viewWillDisappear:(BOOL)animated
{
    [mPlayer pause];    
    [super viewWillDisappear:animated];
    [[UIApplication sharedApplication] endReceivingRemoteControlEvents];
    [self resignFirstResponder];
}

then respond to the

 - (void)remoteControlReceivedWithEvent:(UIEvent *)event {
        switch (event.subtype) {
            case UIEventSubtypeRemoteControlTogglePlayPause:
                if([mPlayer rate] == 0){
                    [mPlayer play];
                } else {
                    [mPlayer pause];
                }
                break;
            case UIEventSubtypeRemoteControlPlay:
                [mPlayer play];
                break;
            case UIEventSubtypeRemoteControlPause:
                [mPlayer pause];
                break;
            default:
                break;
        }
    }

Another trick is needed to resume the reproduction if the user presses the home button (in which case the reproduction is suspended with a fade out).

When you control the reproduction of the video (I have play methods) set

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];

and the corresponding method to be invoked that will launch a timer and resume the reproduction.

- (void)applicationDidEnterBackground:(NSNotification *)notification
{
    [mPlayer performSelector:@selector(play) withObject:nil afterDelay:0.01];
}

Its works for me to play video in Backgorund. Thanks to all.

Adeel Ishaq
  • 101
  • 1
  • 10
Vishal Khatri
  • 954
  • 2
  • 12
  • 32
  • http://www.edumobile.org/iphone/iphone-programming-tutorials/parsing-an-xml-file/ – Vishal Khatri May 28 '13 at 07:52
  • Hi @V.K., I have just setup to play video audio background similar your instruction. But I just only play when Home button pressed, if I turn on Lockscreen. Audio will stop after a few seconds. :( How to I can fix this? – duongvanthai Jun 11 '14 at 15:25
  • [[AVAudioSession sharedInstance] setDelegate: self]; [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; // Add this in AppDelegate, – Vishal Khatri Jun 12 '14 at 11:54
  • I just add this code to AppDelegate, but not solve. In didFinishLaunchingWithOptions, I add: [[AVAudioSession sharedInstance] setDelegate:self]; [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil]; I have view controller use AVPlayer to play video. In this view controller, I add: [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; [self becomeFirstResponder]; ...to get remote control events. It's ok when play in background. But, when locked screen audio will stop while AVPlayer continue running... – duongvanthai Jun 12 '14 at 15:06
  • - (BOOL)canBecomeFirstResponder { return YES; } //.... add this code in AvPlayer Screen and Check in Device – Vishal Khatri Jun 13 '14 at 05:31
  • If you are following all the step from above, than it will definitely works. I have use same and its works in my App. – Vishal Khatri Jun 17 '14 at 08:00
  • @ZAFAR007: all the required code is here only. Please check and let me know what you are searching? – Vishal Khatri Aug 14 '17 at 07:18
  • @VishalKhatri Thanks for your response. i am using above code in my app but it only works on screen lock. when i press home button this NotificationCenter.default.addObserver(self, selector: #selector(applicationDidEnterBackground),name:NSNotification‌​.Name.UIApplicationD‌​idEnterBackground, object: nil) Function call but music didn't resume? any idea – ZAFAR007 Aug 14 '17 at 07:37
3

If you try to change the background mode: Sorry, App store wont approve it.MPMoviePlayerViewController playback video after going to background for youtube

In my research, someone would take the sound track out to play in te background when it goes into background as the video would be pause and get the playbacktime for resume playing when go into foreground

Community
  • 1
  • 1
Horst
  • 1,733
  • 15
  • 20
  • Is there any other way to play video in Background? – Vishal Khatri Mar 19 '13 at 06:04
  • @Horst Can we have functionality like MPMoviePlayerViewController in AVPlayer as well in which Video gets paused when application goes in background and resumes with playbacktime in foreground?? – Zalak Patel Apr 09 '15 at 11:44
  • You may know more about it here: https://developer.apple.com/library/ios/qa/qa1668/_index.html – Horst Apr 10 '15 at 17:50
2

It is not possible to play background music/video using Avplayer. But it is possible using

MPMoviePlayerViewController. I have done this in one of my app using this player & this app

is run successfully to appstore.

Vishal
  • 8,246
  • 6
  • 37
  • 52
  • No dude, Its Possible. see my Answer. Its works perfectly for me. And Thanks for you suggestion. In future i will try with using MPMoviePlayerViewController. – Vishal Khatri Mar 22 '13 at 06:47
  • @V.K. We can pause video when application goes in background and resume it when application is in foreground using AVPlayer? Is it possible to do using AVPlayer? – Zalak Patel Apr 09 '15 at 11:49
2

Try with this snippet, I've already integrated this with my app & it's being useful for me..hope this will work for you!!

Follow the steps given below:

  • Add UIBackgroundModes in the APPNAME-Info.plist, with the selection App plays audio
  • Then add the AudioToolBox framework to the folder frameworks.
  • In the APPNAMEAppDelegate.h add:

    -- #import < AVFoundation/AVFoundation.h>

    -- #import < AudioToolbox/AudioToolbox.h>

  • In the APPNAMEAppDelegate.m add the following:

    // Set AudioSession

     NSError *sessionError = nil;
    
        [[AVAudioSession sharedInstance] setDelegate:self];
    
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:&sessionError];
    
  • /* Pick any one of them */

  • // 1. Overriding the output audio route

//UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker; //AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRouteOverride), &audioRouteOverride);

========================================================================

// 2. Changing the default output audio route

UInt32 doChangeDefaultRoute = 1;

AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryDefaultToSpeaker, sizeof(doChangeDefaultRoute), &doChangeDefaultRoute);

into the

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  • but before the two lines:

    [self.window addSubview:viewController.view];

    [self.window makeKeyAndVisible];

Enjoy Programming!!

Niru Mukund Shah
  • 4,637
  • 2
  • 20
  • 34
  • 1
    When you control the reproduction of the video (I have play methods) set [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; and the corresponding method to be invoked that will launch a timer and resume the reproduction. - (void)applicationDidEnterBackground:(NSNotification *)notification { [mPlayer performSelector:@selector(play) withObject:nil afterDelay:0.01]; } Its works for me – Vishal Khatri Mar 23 '13 at 08:30
  • You should credit the original source of this snippet, Patrick Rorth: https://devforums.apple.com/thread/90684?start=0&tstart=0 – Chris Oct 21 '14 at 15:40
2

Swift version for the accepted answer.

In the delegate:

AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil)
AVAudioSession.sharedInstance().setActive(true, error: nil)

In the view controller that controls AVPlayer

override func viewDidAppear(animated: Bool) {
    UIApplication.sharedApplication().beginReceivingRemoteControlEvents()
    self.becomeFirstResponder()
}

override func viewWillDisappear(animated: Bool) {
    mPlayer.pause()
    UIApplication.sharedApplication().endReceivingRemoteControlEvents()
    self.resignFirstResponder()
}

Don't forget to "import AVFoundation"

MVZ
  • 2,220
  • 5
  • 27
  • 57
1

In addition to fattomhk's response, here's what you can do to achieve video forwarding to the time it should be after your application comes in foreground:

  • Get currentPlaybackTime of playing video when go to background and store it in lastPlayBackTime
  • Store the time when application goes to background (in userDefault probably)
  • Again get the time when application comes in foreground
  • Calculate the duration between background and foreground time
  • Set current playback time of video to lastPlayBackTime + duration
rptwsthi
  • 10,094
  • 10
  • 68
  • 109
0

If you are Playing video using WebView you can handle using javascript to play video on background.

strVideoHTML = @"<html><head><style>body.........</style></head> <body><div id=\"overlay\"><div id=\"youtubelogo1\"></div></div><div id=\"player\"></div> <script> var tag = document.createElement('script'); tag.src = \"http://www.youtube.com/player_api\"; var firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); var player; events: { 'onReady': onPlayerReady, } }); } function onPlayerReady(event) { event.target.playVideo(); } function changeBG(url){ document.getElementById('overlay').style.backgroundImage=url;} function manualPlay() {  player.playVideo(); }  function manualPause() {  player.pauseVideo(); }  </script></body> </html>";

NSString *html = [NSString stringWithFormat:strVideoHTML,url, width, height,videoid;
webvideoView.delegate = self;
[webvideoView loadHTMLString:html baseURL:[NSURL URLWithString:@"http://www.your-url.com"]];

On view diappear call

strscript = @"manualPlay();
[webvideoView stringByEvaluatingJavaScriptFromString:strscript];
Nic Wortel
  • 11,155
  • 6
  • 60
  • 79
Gopal Raju
  • 246
  • 3
  • 12
0

I'd like to add something that for some reason ended up being the culprit for me. I had used AVPlayer and background play for a long time without problems, but this one time I just couldn't get it to work.

I found out that when you go background, the rate property of the AVPlayer sometimes seems to dip to 0.0 (i.e. paused), and for that reason we simply need to KVO check the rate property at all times, or at least when we go to background. If the rate dips below 0.0 and we can assume that the user wants to play (i.e. the user did not deliberately tap pause in remote controls, the movie ended, etc) we need to call .play() on the AVPlayer again.

AFAIK there is no other toggle on the AVPlayer to keep it from pausing itself when app goes to background.

Jonny
  • 15,955
  • 18
  • 111
  • 232