AVAudioSession setCategory Swift 4.2 iOS 12 - Play Sound on Silent

IosSwiftAvfoundationAvaudiosession

Ios Problem Overview


To play sound even on Silent mode I use to use below method. But how it's not working.

// Works on Swift 3  
do {
    try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
} catch {
    print(error)
}

How to get it work in 4.2 / iOS 12?

In newer version we need to set mode and options.

try AVAudioSession.sharedInstance().setCategory(
    <#T##category:AVAudioSession.Category##AVAudioSession.Category#>,
    mode: <#T##AVAudioSession.Mode#>, 
    options: <#T##AVAudioSession.CategoryOptions#>)`

Ios Solutions


Solution 1 - Ios

Her der Töne's comment shows you the new syntax, but you also need to activate the audio session after setCategory:

do {
    try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
    try AVAudioSession.sharedInstance().setActive(true)
} catch {
    print(error)
}

Solution 2 - Ios

As a workaround, you can call the Objective-C AVAudioSession.setCategory: method with the NSObject.performSelector::

if #available(iOS 10.0, *) {
    try! AVAudioSession.sharedInstance().setCategory(.playback, mode: .moviePlayback)
}
else {
    // Workaround until https://forums.swift.org/t/using-methods-marked-unavailable-in-swift-4-2/14949 isn't fixed
    AVAudioSession.sharedInstance().perform(NSSelectorFromString("setCategory:error:"), with: AVAudioSession.Category.playback)
}

If you want to set the category and options for iOS 9 and earlier then use:

AVAudioSession.sharedInstance().perform(NSSelectorFromString("setCategory:withOptions:error:"), with: AVAudioSession.Category.playback, with:  [AVAudioSession.CategoryOptions.duckOthers])
UPDATE:

Issue is fixed in Xcode 10.2.

Solution 3 - Ios

For Swift 4.2 in iOS 12, it is simply:

try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [])

Solution 4 - Ios

Update for Xcode 10.2:

Apple finally fix this issue in Xcode 10.2. 
So no need to add these workaround code anymore if you use Xcode 10.2 or newer version.

But you also could refer this code for any problem like this.

You can use an objective-c category to help to fix this issue.

Create a AVAudioSession+Swift.h:

@import AVFoundation;

NS_ASSUME_NONNULL_BEGIN

@interface AVAudioSession (Swift)

- (BOOL)swift_setCategory:(AVAudioSessionCategory)category error:(NSError **)outError NS_SWIFT_NAME(setCategory(_:));
- (BOOL)swift_setCategory:(AVAudioSessionCategory)category withOptions:(AVAudioSessionCategoryOptions)options error:(NSError **)outError NS_SWIFT_NAME(setCategory(_:options:));

@end

NS_ASSUME_NONNULL_END

With a AVAudioSession+Swift.m:

#import "AVAudioSession+Swift.h"

@implementation AVAudioSession (Swift)

- (BOOL)swift_setCategory:(AVAudioSessionCategory)category error:(NSError **)outError {
    return [self setCategory:category error:outError];
}
- (BOOL)swift_setCategory:(AVAudioSessionCategory)category withOptions:(AVAudioSessionCategoryOptions)options error:(NSError **)outError {
    return [self setCategory:category withOptions:options error:outError];
}

@end

Then import the "AVAudioSession+Swift.h" in your <#target_name#>-Bridging-Header.h

#import "AVAudioSession+Swift.h"

Result is you can call the method in swift like before.

do {
    try AVAudioSession.sharedInstance().setCategory(.playback)
    try AVAudioSession.sharedInstance().setCategory(.playback, options: [.mixWithOthers])
    try AVAudioSession.sharedInstance().setActive(true)
} catch {
    print(error)
}

Solution 5 - Ios

The above answer (by Rhythmic Fistman) is correct if your app is not compatible with iOS 9 or below.

If your app is compatible with iOS 9 you will see the next error:

> 'setCategory' is unavailable in Swift

In that case there is a bug with Swift 4.2, this is an issue with AVFoundation in Xcode 10's SDKs, you can work around it by writing an Objective-C function that calls through to the old API, since they're still available in Objective-C.

In the next link you can read more details:

https://forums.swift.org/t/using-methods-marked-unavailable-in-swift-4-2/14949

Solution 6 - Ios

Paste this into your viewDidLoad()

do {
    try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback, mode: AVAudioSession.Mode.default, options: [])
    try AVAudioSession.sharedInstance().setActive(true)
}
catch {
    print(error)
}

Solution 7 - Ios

//Swift 4.2
if #available(iOS 10.0, *) {
    try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, 
    mode: AVAudioSessionModeDefault)
} else {
 //Fallback on earlier versions
}

Solution 8 - Ios

Swift 5

let audioSession = AVAudioSession.sharedInstance()
_ = try? audioSession.setCategory(.playback, options: .defaultToSpeaker)
_ = try? audioSession.setActive(true)

Solution 9 - Ios

Code for swift 4 :

do {
        try AKSettings.setSession(category: .playback, with: [])
        try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, mode: AVAudioSessionModeDefault, options: [])
        try AVAudioSession.sharedInstance().setActive(true)
        
        
    } catch {
        print(error)
    }

Hope that helps

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNiteshView Question on Stackoverflow
Solution 1 - IosRhythmic FistmanView Answer on Stackoverflow
Solution 2 - IosricardopereiraView Answer on Stackoverflow
Solution 3 - IosChewie The ChorkieView Answer on Stackoverflow
Solution 4 - IosGalvinView Answer on Stackoverflow
Solution 5 - IosJMGMView Answer on Stackoverflow
Solution 6 - IosWill ReynoldsView Answer on Stackoverflow
Solution 7 - IosPiyush SharmaView Answer on Stackoverflow
Solution 8 - IosbudiDinoView Answer on Stackoverflow
Solution 9 - IosSasan SoroushView Answer on Stackoverflow