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.
-
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 Answers
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.
-
Thanks for the quick reply I will look into the method sometime in the next few hours :) – Nick0014 Feb 05 '17 at 00:24
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 :)

- 713
- 12
- 16