I am currently working on a PTT (push-to-talk) app. I am trying to use to hardware volume buttons to start/stop transmission.
All suggested solutions I've seen so far can be narrowed down to two:
AVAudioSession
property outputVolume
.AVSystemController_SystemVolumeDidChangeNotification
and since iOS 15.0 - SystemVolumeDidChange
.Without getting into the pros and cons of each solution, they both have one thing in common - they are volume based, which raises several problems.
I have noticed that Zello app has somehow managed to overcome those issues, as they enable the usage of volume buttons even when device is closed or when command center is open - without any interference to the system volume. In addition changing volume from command center has not effect.
Does anyone have any idea as to how to achieve such a behavior?
Warning Private API usage follows. You MUST have some special circumstances that may allow you to get through AppStore Review.
Take look at Explore the iOS SDK and use undocumented APIs from 2012.
To summarise, you need to call the private method - [UIApplication setWantsVolumeButtonEvents:YES]
to enable the following notifications:
_UIApplicationVolumeUpButtonDownNotification
_UIApplicationVolumeUpButtonUpNotification
_UIApplicationVolumeDownButtonDownNotification
_UIApplicationVolumeDownButtonUpNotification
In Swift this can be enabled with something like:
@objc public protocol UIApplicationPrivate {
@objc func setWantsVolumeButtonEvents(_:Bool)
}
class VolumeButtonsManager {
private static var observer: NSObjectProtocol?
static func setup(with application: UIApplication) {
observer = NotificationCenter.default.addObserver(forName: nil,
object: nil,
queue: nil,
using: handleEvent)
let application = unsafeBitCast(application, to:UIApplicationPrivate.self)
application.setWantsVolumeButtonEvents(true)
}
private static func handleEvent(_ notification: Notification) {
switch notification.name.rawValue {
case "_UIApplicationVolumeUpButtonDownNotification": print("Volume Up Button Down")
case "_UIApplicationVolumeUpButtonUpNotification": print("Volume Up Button Up")
case "_UIApplicationVolumeDownButtonDownNotification": print("Volume Down Button Down")
case "_UIApplicationVolumeDownButtonUpNotification": print("Volume Down Button Up")
default: break
}
}
}
UIApplicationPrivate
via Silencing a warning for explicitly constructed selector.