0

so my problem is that I'm creating an app which uses local notifications as an alarm. The only issue is that if the device has its ringer volume down or on silent, it will not play any sound. I am aware that you are unable to do this in the background however is it possible to have a slider linked up to the ringer volume (like a slider for MPVolume)? Also is it possible to check whether the device is muted? Again I just want to point out I am aware that you cannot simply change it without the user knowing but I was wondering whether the two methods stated earlier are possible. Any help on the topic will be greatly appreciated.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Nick0014
  • 5
  • 1
  • 3
  • http://stackoverflow.com/questions/3651252/how-to-get-audio-volume-level-and-volume-changed-notifications-on-ios might be useful – matt Feb 05 '17 at 00:00
  • Hi thanks for the reply. Is system volume (what they are referring to in that link), include the ringer volume? – Nick0014 Feb 05 '17 at 00:23

2 Answers2

0

It is not possible to detect if an iPhone has its silence switch on or to change the "Ringer" (Not Volume) as Apple does not provide access to them.

There used to be a workaround a while back using Objective-C but I'm not quite sure if it still works, you are welcome to try if you want to.

AVSystemController

Community
  • 1
  • 1
Mentos
  • 483
  • 1
  • 4
  • 14
0

Also is it possible to check whether the device is muted?

This issue is really frustrating and I can't believe Apple makes it so hard :(

Checking the volume itself is rather simple:

let audioSession = AVAudioSession.sharedInstance()
let volume: Float = audioSession.outputVolume

If volume is 0.0, it's silent. But the real problem is the ringer switch.

My solution is to play a silent sound (called "silence.mp3" which is 1.5 sec long and all silent) and check after 0.5 sec if it's still being played. This is totally inspired by the SoundSwitch: https://github.com/moshegottlieb/SoundSwitch

In usage:

MyAudioPlayer.isLoudCheck()
{
    isLoud in

    print("%%% - device is loud = \(isLoud)")
}

I changed the audio player class to this (usually I just use it to play sound files):

import AVFoundation

class MyAudioPlayer: NSObject, AVAudioPlayerDelegate
{
    private static let sharedPlayer: MyAudioPlayer =
    {
        return MyAudioPlayer()
    }()

    public var container = [String : AVAudioPlayer]()

    static func isLoudCheck(completionHandler: @escaping (Bool?) -> ())
    {
        let name = "silence"
        let key = name
        var player: AVAudioPlayer?

        for (file, thePlayer) in sharedPlayer.container
        {
            if file == key
            {
                player = thePlayer
                break
            }
        }

        if player == nil, let resource = Bundle.main.path(forResource: name, ofType: "mp3")
        {
            do
            {
                player = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: resource), fileTypeHint: AVFileTypeMPEGLayer3)
            }
            catch
            {
                print("%%% - audio error?")
            }
        }

        if let thePlayer = player
        {
            print("%%% - the player plays")
            thePlayer.delegate = sharedPlayer
            sharedPlayer.container[key] = thePlayer
            thePlayer.play()
        }


        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute:
        {
            if let thePlayer = player
            {
                if thePlayer.isPlaying
                {
                    print("%%% - check: playing")
                    completionHandler(true)
                }
                else
                {
                    print("%%% - check: not playing")
                    completionHandler(false)
                }
            }
        })
    }

    static func isPlaying(key: String) -> Bool?
    {
        return sharedPlayer.container[key]?.isPlaying
    }
}

Hope this helps someone :)

Colibri
  • 713
  • 12
  • 16