I am working on calling App.So when the call is received I want to play a native sound. It's working but my problem is when the phone is silent, phone only vibrates.And when silent is off play sound.I am using below code to achieve this. But it's not working.Please tell me what I do?
// play sound when call is coming
func playSound()
{
guard let url = URL(string: "/Library/Ringtones/Opening.m4r") else
{
print("url not found")
return
}
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
print(error)
}
player = try? AVAudioPlayer(contentsOf: url)
player?.numberOfLoops = -1
player?.prepareToPlay()
player?.play()
}
I am creating an application using xcode 7.1, swift. I want to play an audio. Everything is fine. Now my problem I want to hear sound when the device in silent mode or muted. How can I do it?
I am using the following code to play audio
currentAudio!.stop()
currentAudio = try? AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("sample_audio", ofType: "mp3")!));
currentAudio!.currentTime = 0
currentAudio!.play();
Put this line before calling play() method of AVPlayer.
In Objective C
[[AVAudioSession sharedInstance]
setCategory: AVAudioSessionCategoryPlayback
error: nil];
In Swift
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
} catch {
// report for an error
}
Swift 5
do {
try AVAudioSession.sharedInstance().setCategory(.playback)
} catch(let error) {
print(error.localizedDescription)
}
You can use AppDelegate class.
For enable sound (for audio or video) when device is in silent mode use AVAudioSessionCategoryPlayback:
func applicationDidBecomeActive(_ application: UIApplication) {
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
} catch {
print("AVAudioSessionCategoryPlayback not work")
}
}
For disable sound when device is in silent mode (for example when we answer the phone call) use AVAudioSessionCategorySoloAmbient:
func applicationWillResignActive(_ application: UIApplication) {
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategorySoloAmbient)
} catch {
print("AVAudioSessionCategorySoloAmbient not work")
}
}
Swift 4
use this line before play video
try? AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [])
Swift 3.0 and Xcode > 8
Play sound in Video when device is on RINGER mode and SLIENT mode
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
//print("AVAudioSession Category Playback OK")
do {
try AVAudioSession.sharedInstance().setActive(true)
//print("AVAudioSession is Active")
} catch _ as NSError {
//print(error.localizedDescription)
}
} catch _ as NSError {
//print(error.localizedDescription)
}
Swift 4.2
do {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [])
} catch let error {
print("Error in AVAudio Session\(error.localizedDescription)")
}
Swift 5.0.1
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback)
You can go through this, it will help you out
When you use following audio session categories, sounds will not be muted on iOS: AVAudioSessionCategoryPlayback,AVAudioSessionCategoryRecord,AVAudioSessionCategoryPlayAndRecord
Example
func playSound (Sound: String, Type: String) {
//Prepare the sound file name & extension
var alertSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(Sound, ofType: Type)!)
//Preparation to play
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil)
AVAudioSession.sharedInstance().setActive(true, error: nil)
//Play audio
var error: NSError?
audioPlayer = AVAudioPlayer(contentsOfURL: alertSound, error: &error)
audioPlayer.prepareToPlay()
audioPlayer.play()
}
import AVKit
And add this to your AppDelegate's applicationDidBecomeActive section
func applicationDidBecomeActive(_ application: UIApplication) {
// 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.
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback)
print("AVAudioSession Category Playback OK")
do {
try AVAudioSession.sharedInstance().setActive(true)
print("AVAudioSession is Active")
} catch {
print(error.localizedDescription)
}
} catch {
print(error.localizedDescription)
}
}
I'm developing a live video player and I want to use the new Picture in Picture option. I based the player on an AVPlayerViewController and this is my code.
class PlayerViewController: AVPlayerViewController {
var link = NSURL ()
override func viewDidLoad() {
super.viewDidLoad()
setVideoPlayer()
do {
try AVAudioSession.sharedInstance().setActive(true)
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
}
catch {
print("Audio session setCategory failed")
}
}
}
typealias VideoPlayer = PlayerViewController
extension VideoPlayer {
func setVideoPlayer() {
player = AVPlayer(URL: (link))
player!.play()
}
}
I don't understand why PictureInPicture works well on iPad Air 2 simulator but in the real device the PiP button stays disabled although visible, and the user can't click on it.
Make sure to set audio session in AppDelegate.swift func application(application:, didFinishLaunchingWithOptions launchOptions:) find below the sample code .
let audioSssn = AVAudioSession.sharedInstance();
do {
try audioSssn.setCategory(AVAudioSessionCategoryPlayback)
}
catch {
print("Audio session setCategory failed")
}
Forgive me if this question has been asked already, but I've looked everywhere and all I can find is old questions from iOS 5.0 and people have the opposite problem.
My problem is I have created a video I would like to use in my application, and I recently added audio to it. The video plays fine with no problems, but the audio does not play. If I play the video in any video player in my computer, the sound is there so I cant figure out what the problem is.
Here is my code:
var movieViewController: MPMoviePlayerViewController?
func playVideoUsingViewController() {
if let
path = NSBundle.mainBundle().pathForResource("wakyIntro", ofType: "mp4"),
url = NSURL(fileURLWithPath: path),
movieViewController = MPMoviePlayerViewController(contentURL: url) {
self.movieViewController = movieViewController
movieViewController.moviePlayer.fullscreen = true
movieViewController.moviePlayer.controlStyle = .None
movieViewController.moviePlayer.scalingMode = .AspectFill
movieViewController.view.userInteractionEnabled = false
self.showViewController(movieViewController, sender: self)
println("Movie loaded")
} else {
println("Video failed")
}
}
Then I just call it from my ViewController:
func mainMenuViewControllerDidPressPlay(mainMenuViewController: MainMenuViewController) {
game?.runAction(pressButton)
if !videoPlayed{
playVideoUsingViewController()
} else if !gameStarted {
gameStarted = true
game?.bird.startAnimation(game!)
game?.bird.startPhysics()
}
self.hideViewController(mainMenuViewController)
}
Any ideas or suggestions would be greatly appreciated!
This is a solution in swift based on #user2709666's response
var session: AVAudioSession = AVAudioSession.sharedInstance()
session.setCategory("AVAudioSessionCategoryPlayback", withOptions: AVAudioSessionCategoryOptions.DefaultToSpeaker, error: nil)
Call this before playing the video.
Edit for Swift 2.2 :
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
} catch let error as NSError {
print(error)
}
Make a session of AVAudioSession.
Following is the code:
var session = AVAudioSession.SharedInstance();
session.SetCategory(new NSString("AVAudioSessionCategoryPlayback"), AVAudioSessionCategoryOptions.DefaultToSpeaker, out error);
if (error != null)
{
Console.WriteLine(error);
}
and add this before your video player. I am sure this will work for you, I got the same issue before.
I created an app and I am attempting to allow the user to continue to listen to their music while playing my game, but whenever they hit "play" and the ingame sounds occur it will stop the background music. I am developing on iOS using Swift. Here is a piece of the code that initiates the ingame sounds.
func playSpawnedDot() {
var alertSound: NSURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("spawnDot", ofType: "mp3")!)!
var error:NSError?
audioPlayer = AVAudioPlayer(contentsOfURL: alertSound, error: &error)
audioPlayer.prepareToPlay()
if volumeBool {
audioPlayer.play()
}
}
You need to set the AVAudioSession category, with one of the following value: https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioSession_ClassReference/index.html (AVAudioSession Class Reference).
The default value is set to AVAudioSessionCategorySoloAmbient. As you can read :
[...] using this category implies that your app’s audio is nonmixable—activating your session will interrupt any other audio sessions which are also nonmixable. To allow mixing, use the AVAudioSessionCategoryAmbient category instead.
You have to change the category, before you play your sound. To do so :
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient, error: nil)
AVAudioSession.sharedInstance().setActive(true, error: nil)
You don't need to call those line each time you play the sound. You might want to do it only once.
Swift 4 version:
try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient)
try? AVAudioSession.sharedInstance().setActive(true)
This is how I do it in Swift 3.0
var songPlayer : AVAudioPlayer?
func SetUpSound() {
if let path = Bundle.main.path(forResource: "TestSound", ofType: "wav") {
let filePath = NSURL(fileURLWithPath:path)
songPlayer = try! AVAudioPlayer.init(contentsOf: filePath as URL)
songPlayer?.numberOfLoops = -1 //logic for infinite loop
songPlayer?.prepareToPlay()
songPlayer?.play()
}
let audioSession = AVAudioSession.sharedInstance()
try!audioSession.setCategory(AVAudioSessionCategoryPlayback, with: AVAudioSessionCategoryOptions.duckOthers) //Causes audio from other sessions to be ducked (reduced in volume) while audio from this session plays
}
You can see more of AVAudioSessionCategoryOptions here: https://developer.apple.com/reference/avfoundation/avaudiosessioncategoryoptions
Here's what I am using for Swift 2.0:
let sess = AVAudioSession.sharedInstance()
if sess.otherAudioPlaying {
_ = try? sess.setCategory(AVAudioSessionCategoryAmbient, withOptions: .DuckOthers)
_ = try? sess.setActive(true, withOptions: [])
}
Please note that you can replace .DuckOthers with [] if you don't want to lower background music and instead play on top to it.
Since they can't seem to make up their minds from version to version. Here it is in Swift 5.0
do{
try AVAudioSession.sharedInstance().setCategory(.ambient)
try AVAudioSession.sharedInstance().setActive(true, options: .notifyOthersOnDeactivation)
} catch {
NSLog(error.localizedDescription)
}
lchamp's solution worked perfectly for me, adapted for Objective-C:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
[[AVAudioSession sharedInstance] setActive:YES error:nil];
**
Updated for Swift 3.0
**
The name of the sound I am playing is shatter.wav
func shatterSound() {
if let soundURL = Bundle.main.url(forResource: "shatter", withExtension: "wav") {
var mySound: SystemSoundID = 0
AudioServicesCreateSystemSoundID(soundURL as CFURL, &mySound)
AudioServicesPlaySystemSound(mySound);
}
}
Then where ever you want to play the sound call
shatterSound()
If you want to play an alert sound:
public func playSound(withFileName fileName: String) {
if let soundUrl = Bundle.main.url(forResource: fileName, withExtension: "wav") {
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient, with:[.duckOthers])
try AVAudioSession.sharedInstance().setActive(true)
var soundId: SystemSoundID = 0
AudioServicesCreateSystemSoundID(soundUrl as CFURL, &soundId)
AudioServicesAddSystemSoundCompletion(soundId, nil, nil, { (soundId, clientData) -> Void in
AudioServicesDisposeSystemSoundID(soundId)
do {
// This is to unduck others, make other playing sounds go back up in volume
try AVAudioSession.sharedInstance().setActive(false)
} catch {
DDLogWarn("Failed to set AVAudioSession to inactive. error=\(error)")
}
}, nil)
AudioServicesPlaySystemSound(soundId)
} catch {
DDLogWarn("Failed to create audio player. soundUrl=\(soundUrl) error=\(error)")
}
} else {
DDLogWarn("Sound file not found in app bundle. fileName=\(fileName)")
}
}
And if you want to play music:
import AVFoundation
var audioPlayer:AVAudioPlayer?
public func playSound(withFileName fileName: String) {
if let soundUrl = Bundle.main.url(forResource: fileName, withExtension: "wav") {
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient, with:[.duckOthers])
try AVAudioSession.sharedInstance().setActive(true)
let player = try AVAudioPlayer(contentsOf: soundUrl)
player.delegate = self
player.prepareToPlay()
DDLogInfo("Playing sound. soundUrl=\(soundUrl)")
player.play()
// ensure the player does not get deleted while playing the sound
self.audioPlayer = player
} catch {
DDLogWarn("Failed to create audio player. soundUrl=\(soundUrl) error=\(error)")
}
} else {
DDLogWarn("Sound file not found in app bundle. fileName=\(fileName)")
}
}
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
self.audioPlayer?.stop()
do {
// This is to unduck others, make other playing sounds go back up in volume
try AVAudioSession.sharedInstance().setActive(false)
} catch {
DDLogWarn("Failed to set AVAudioSession inactive. error=\(error)")
}
}
For Swift (Objective-C like this too)
you can use this link for best answer and if you don't have any time for watching 10 minutes the best action is that you just copy below code in your AppDelegate in didFinishLaunchingWithOptions and then select your project's target then go to Capabilities and at last in Background modes check on Audio, AirPlay and Picture in Picture
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let session = AVAudioSession.sharedInstance()
do {
try session.setCategory(AVAudioSessionCategoryPlayback)
}
catch {
}
}
I didn't think that just setting the AVAudioSession to AVAudioSessionCategoryOptions.duckOthers would work, but it did. Here is my full code to help the rookies like myself.
Swift 4 - Full Example:
var audioPlayer = AVAudioPlayer()
func playSound(sound: String){
let path = Bundle.main.path(forResource: sound, ofType: nil)!
let url = URL(fileURLWithPath: path)
let audioSession = AVAudioSession.sharedInstance()
try!audioSession.setCategory(AVAudioSessionCategoryPlayback, with: AVAudioSessionCategoryOptions.duckOthers)
do {
audioPlayer = try AVAudioPlayer(contentsOf: url)
audioPlayer.play()
} catch {
print("couldn't load the file")
}
}
I still need to figure out setActive (I was looking at this blog post) but the audio stops ducking when I leave the app, so it works for my app.
Swift 5 Version based on lchamp`s answer.
try? AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.ambient)
try? AVAudioSession.sharedInstance().setActive(true)
This works perfectly for me on iOS 14.4 and Swift 5. It's a bit different answer from others by using the .duckOthers option (and you can also mix directly with sound if you'd like with .mixWithOthers), but it works perfectly while music plays. It will lower the volume of the music, play the "beep" sound, and then raise the music volume back up to normal. It also captures error data using Google Firebase Crashlytics if there is an issue, and tries to raise the volume to normal even on an error.
This code will also work perfectly on the first, and all other, plays of your sound without it stopping the music ever.
func playSound() {
do {
if let path = Bundle.main.path(forResource: "beep", ofType: "mp3") {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: .duckOthers)
try AVAudioSession.sharedInstance().setActive(true)
let filePath = NSURL(fileURLWithPath:path)
songPlayer = try AVAudioPlayer.init(contentsOf: filePath as URL)
songPlayer?.numberOfLoops = 0
songPlayer?.prepareToPlay()
songPlayer?.play()
try AVAudioSession.sharedInstance().setActive(false)
}
} catch (let error) {
try? AVAudioSession.sharedInstance().setActive(false)
Crashlytics.crashlytics().setCustomValue(error.localizedDescription, forKey: "audio_playback_error")
}
}
An important thing the others answers do not have is that you need to call false with the .notifyOthers flag when deactivating:
try AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
The reason for this is that other apps playing music in the background will know when to turn their audio back on when you deactivate yours. Otherwise your background music won't turn back on if you turned off your session.