Currently I am working on an app, where I have to play some voicemail messages using Play button.So I have to employ MPVolumeView to let user to switch over different audio routes. Below is my code snippet how I am adding the view to my view controller:
let volumeView = MPVolumeView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
volumeView.showsVolumeSlider = false
volumeView.tintColor = UIColor.gray
for subview in volumeView.subviews {
if let slider = subview as? UISlider {
slider.isHidden = true
slider.frame = CGRect.zero
break
}
}
if let airPlayButton = volumeView.subviews.first(where: { $0 is UIButton }) as? UIButton {
//let customImage = UIImage(R.image.ic_airpods_bluetooth_dark)?.withRenderingMode(.alwaysTemplate)
airPlayButton.setImage(R.image.ic_airpods_bluetooth_dark(), for: .normal)//airPlayButton.setImage(customImage, for: .normal)
airPlayButton.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
_ = airPlayButton.imageView
let symbolConfiguration = UIImage.SymbolConfiguration(pointSize: 40, weight: .regular)
let sfSymbol = UIImage(systemName: "airplayvideo.circle.fill", withConfiguration: symbolConfiguration)
airPlayButton.setImage(sfSymbol, for: .normal)
}
self.vwMV.addSubview(volumeView)
And here is how I am initiating the audio session:
audioSession = AVAudioSession.sharedInstance()
do {
try audioSession?.setCategory(.playAndRecord, options: .allowBluetooth)
try audioSession?.setActive(true)
//try audioSession?.overrideOutputAudioPort(.none)
} catch {
print("Failed to set audio session category: \(error)")
}
NotificationCenter.default.addObserver(self, selector: #selector(routeChangeEventHandle), name: AVAudioSession.routeChangeNotification, object: nil)
Problem is, I am facing the 2 serious bugs with the above implementations:
- I don't get Phones earpiece and Speaker options always
- However, When I get both option, when I switch to Speaker options, the dialog shows me that as iPhone, after clicked. Please check the image below:

