27

Good day,

My app is a music playing app. I control the <audio>-Tag with Javascript. So far no problems, play, pause, next and previous buttons are working. When I stand-by the device in iOS 5, the music keeps playing, but the automatic next song doesn't work. When it isn't in stand-by, it works. And in iOS 6, just after pressing the button, the music fades out.

The Play/Pause button on the lockscreen works in iOS 5, but not in iOS 6.

Adexe Rivera
  • 414
  • 7
  • 12
heysamhey
  • 530
  • 1
  • 6
  • 17

4 Answers4

73

Starting with iOS 6, you MUST set the audio session category to 'playback' before creating the UIWebView. This is all you have to do. It is not necessary to make the session active.

This should be used for html video as well, because if you don't configure the session, your video will be muted when the ringer switch is off.

#import <AVFoundation/AVFoundation.h>

AVAudioSession *audioSession = [AVAudioSession sharedInstance];
BOOL ok;
NSError *setCategoryError = nil;
ok = [audioSession setCategory:AVAudioSessionCategoryPlayback
                         error:&setCategoryError];
if (!ok) {
  NSLog(@"%s setCategoryError=%@", __PRETTY_FUNCTION__, setCategoryError);
}

Ensure that your target links to the AVFoundation framework.


If using Cordova, the file you need to modify is platforms/ios/MyApp/Classes/AppDelegate.m, and will end up looking like this:

#import "AppDelegate.h"
#import "MainViewController.h"
#import <AVFoundation/AVFoundation.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    BOOL ok;
    NSError *setCategoryError = nil;
    ok = [audioSession setCategory:AVAudioSessionCategoryPlayback error:&setCategoryError];
    if (!ok) {
        NSLog(@"%s setCategoryError=%@", __PRETTY_FUNCTION__, setCategoryError);
    }

    self.viewController = [[MainViewController alloc] init];
    return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

@end

Also, as mentioned in the comments, you need to link the AVFoundation Framework, as explained in this answer:

  • Open your project with xcode open ./platforms/ios/MyApp.xcworkspace/
  • Project navigator > target My App > General
  • Scroll to the bottom to find Linked Frameworks and Libraries
Jaime Gómez
  • 6,961
  • 3
  • 40
  • 41
Chris Lundie
  • 6,023
  • 2
  • 27
  • 28
  • 3
    Wow, this appears to be related to a similar problem I'm having. Where did you find this out? Is there documentation anywhere about what changed in iOS6 with UIWebView / AVAudioSession? – strawtarget Sep 25 '12 at 18:18
  • The iOS 6 release notes say that UIWebView does not set the audio playback session anymore, so you must do it yourself. The note was possibly only added in the GM release. At least, I had this problem during the beta period but didn't find a fix until the GM. – Chris Lundie Sep 25 '12 at 19:06
  • 5
    I've never done any Objective-C and have no idea what i should do with this code snippet, could you explan to me? – heysamhey Oct 27 '12 at 13:54
  • Is it necessary to do it before the webview is created, or can it be done later when the playback has started? – ySgPjx Nov 18 '12 at 16:16
  • 2
    @heysamhey this code can be placed in ViewController.m. The import statement should go at the top, and the rest can go in `viewDidLoad`. To link the AVFoundation framework, check [this answer on SO](http://stackoverflow.com/questions/19337890/how-to-add-an-existing-framework-in-xcode-5/19337932#19337932). – block14 Jan 24 '14 at 16:37
  • How to prevent pausing a video burring switching to background? – Danil Mar 22 '14 at 15:46
  • 2
    @ChrisLundie maybe you should add that audio background mode needs to be enabled in XCode capabilities tab as well. Just for completeness' sake :-) – bk138 May 04 '15 at 17:06
  • Previously, this solution had worked perfectly for me in every Cordova app. But it seems that Cordova iOS 4.0.1 may have done something to break this, because I've used the exact same code but the background audio still doesn't function. To remedy this, I've instead just used a background audio plugin, which doesn't require manual entry of class files: https://www.npmjs.com/package/nl.kingsquare.cordova.background-audio – kdpnz Feb 16 '16 at 23:18
  • Is this workaround still work in the latest iOS 13.4.1? –  May 07 '20 at 07:45
2

Swift Syntax:

in AppDelegate:

import AVFoundation

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
  do{
      let audio = AVAudioSession.sharedInstance()
      try audio.setCategory(AVAudioSession.Category.playback)
  }catch let error as NSError{
     print(error)
  }
}
kevnk
  • 18,733
  • 3
  • 28
  • 30
Weles
  • 1,275
  • 13
  • 17
1

This plugin will make your app ignore the mute switch. It's basically the same code that's in the other answers but it's nicely wrapped into a plugin so that you don't have to do any manual objective c edits.

https://github.com/EddyVerbruggen/cordova-plugin-backgroundaudio

Run this command to add it to your project:

cordova plugin add https://github.com/EddyVerbruggen/cordova-plugin-backgroundaudio.git
Dev01
  • 13,292
  • 19
  • 70
  • 124
0

Here the SWIFT 2.0 version to set the audio session category to 'playback' before creating the UIWebView.

do {
    try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
}
catch let error as NSError {
    print(error)  
}

do {
    try AVAudioSession.sharedInstance().setActive(true)
}
catch let error as NSError {
    print(error)  
}
Aaleks
  • 4,283
  • 5
  • 31
  • 39
  • Is there any such method for inline videos that can play audio when the app enters the background. Currently, when the app enters the background, the audio stops playing. However, I can pull up Control Centre and continue playing at any time. – JDev Jan 19 '17 at 21:19