11

I have a UIWebView that plays video clips in my view controller. When I exit the app, the audio will stop playing, although I can press play in the control center to continue it again. To do that I'm using the following code in my AppDelegate.swift.

When the app enters the background, I'd like the audio to start playing automatically. How can I enable the MPMusicPlayerController/AVAudioPlayer (I'm really not sure which it is) to continue playing so the user doesn't have to manually press play?

I also have "Audio and Airplay" checked under Background Modes in my target settings, and Required Background Modes set to "App plays audio or streams audio/video using AirPlay".

var error: NSError?
var success = AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: &error)
if !success {
     NSLog("Failed to set audio session category.  Error: \(error)")
}

UPDATE: I'm creating a custom view in my appDel to accommodate a video mini player. Here's how I'm creating it. CustomWindow is a custom class of UIWindow where I'm adding a mini player to the top of the view hierarchy. In this code, am I calling that method before creating the UIWebView?

class AppDelegate: UIResponder, UIApplicationDelegate {

    let myWind = CustomWindow(frame:UIScreen.mainScreen().bounds)
    var window: UIWindow? {
        set {

        }
        get {
            return myWind
        }
    }

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

        var error: NSError?
        var success = AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: &error)
        if success {
            AVAudioSession.sharedInstance().setActive(true, error: nil)
            UIApplication.sharedApplication().beginReceivingRemoteControlEvents()
        } else {
            NSLog("Failed to set audio session category.  Error: \(error)")
        }

        myWind.showOrHidePopupWindow()
}
slider
  • 2,736
  • 4
  • 33
  • 69

3 Answers3

5

Try to update you code with this:

var error: NSError?
var success = AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: &error)
if success {
    AVAudioSession.sharedInstance().setActive(true, error: nil)
    UIApplication.sharedApplication().beginReceivingRemoteControlEvents() 
} else {
    NSLog("Failed to set audio session category.  Error: \(error)")
}

Important:

  1. Don't use simulator for tests. Background playback doesn't work in the Simulator;
  2. Call above code before creating UIWebView instance.

Sources: 1, 2.

Community
  • 1
  • 1
Vlad Papko
  • 13,184
  • 4
  • 41
  • 57
  • I added that block of code to the top of `applicationDidFinishLaunchingWithOptions` but to no luck. Although I'm not entirely convinced I'm calling it before creating `UIWebView`. Can you take a look at my updated code? – slider Aug 04 '15 at 17:48
  • @dperk Are you using storyboard for you UIWebView object? – Vlad Papko Aug 04 '15 at 18:22
  • No I'm setting it programmatically – slider Aug 04 '15 at 18:34
  • @dperk can you put two breakpoints: one in `didFinishLoadingWithLaunching` method, another one in method where you setting `UIWebView` object. And see which breakpoint fires first. – Vlad Papko Aug 04 '15 at 18:44
  • `let myWind=` is being called before `didFinishLaunchingWithOptions` – slider Aug 04 '15 at 18:53
  • @dperk try then initialize myWind object inside `applicationDidFinishLaunchingWithOptions` method. Put it after the code related to `AVAudioSession`. – Vlad Papko Aug 04 '15 at 18:57
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/85139/discussion-between-dperk-and-visput). – slider Aug 04 '15 at 19:05
  • So I added the AV code right before creating and adding the webview, but no luck. That code works with webview videos too? – slider Aug 05 '15 at 03:35
  • I just need the video to either not pause, or resume playback, when it enters the background state – slider Aug 05 '15 at 03:46
  • Still no luck. I can play the video's audio by swiping up from control center and pressing play, but I want playback to be automatic upon entering background mode – slider Aug 11 '15 at 05:06
4

You can play music in lockscreen with

var error: NSError?
var success = AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: &error)
if success {
    AVAudioSession.sharedInstance().setActive(true, error: nil)
    UIApplication.sharedApplication().beginReceivingRemoteControlEvents() 
} else {
    NSLog("Failed to set audio session category.  Error: \(error)")
}

After it You Need to add Background Modes in the capabilities Like this. And don't test this on simulator It does not work on simulator. Hope it helpsenter image description here

and this is how you can handal previous,next,pause and play :-

- (void) remoteControlReceivedWithEvent: (UIEvent *) receivedEvent

 {

    if (receivedEvent.type == UIEventTypeRemoteControl) 
{
        switch (receivedEvent.subtype)
 {
            case UIEventSubtypeRemoteControlTogglePlayPause:
                [self togglePlayPause];
                break;
            case UIEventSubtypeRemoteControlPreviousTrack:
                [self playPrevTrack];
                break;
            case UIEventSubtypeRemoteControlNextTrack:
                [self playNextTrack];
                break;
            default:
                break;
        }
    }
}

In swift you can use it Like that

override func remoteControlReceivedWithEvent(event: UIEvent) {
        let rc = event.subtype

        println("received remote control \(rc.rawValue)") // 101 = pause, 100 = play
        switch rc {
        case .RemoteControlTogglePlayPause:

            self.togglePlayPause()
        break;
        case .RemoteControlPreviousTrack:
            self.playPrevTrack()
         break;
        case .RemoteControlNextTrack:
            self.playNextTrack()
        break;
        default:break
        }
chakshu
  • 1,372
  • 2
  • 10
  • 21
  • In Swift, there's no `self.togglePlayPause` etc. How should I call it from `appDelegate.Swift`? – slider Aug 10 '15 at 07:47
  • togglePlayPause is your method to play and pause method. I have updated my answer for swift. – chakshu Aug 10 '15 at 08:34
  • Let me know if you need more help. – chakshu Aug 10 '15 at 08:34
  • please accept this answer if it solve your problem. Thanks Happy coding. – chakshu Aug 10 '15 at 08:39
  • This isn't accomplishing what I want. The media should play automatically upon entering background mode. This only gets called if I swipe up from control center and toggle play pause myself. – slider Aug 10 '15 at 18:09
-1

A common "trick" is to play a white sound that keeps your app running. But it will display a red bold status bar

The Windwaker
  • 1,054
  • 12
  • 24