So, you’re writing an awesome multimedia application for the iPhone. Everything’s going swimmingly, and you even have some nice animation effects for when the iPhone is plugged into an external accessory, just like the iPod app:
1 2 3 4 5 6 7 8 9 | |
Or something like that. That’s purely to illustrate what you might be doing in response to a run-of-the-mill hardware route change (headphones plugged in, connected to speaker dock, etc.), which of course you’re detecting like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
This has been documented in plenty of places. Then, you flip the Ring/Vibrate switch and everything grinds to a halt. Your route change callback doesn’t get called, and now your MPVolumeView declares to the world that the volume isn’t available. Of course it’s not available. That’s why we’re going to all this trouble - to hide the volume slider when we aren’t permitted to change it!
After a long time pondering this problem (it’s been on the backburner for about a week), I eventually realized that the route change callback might be dependent on the so-called ”category” of the AudioSession. For example, if your app just plays alert sounds occasionally, you (probably) don’t want them sounding when the phone is set to vibrate. On the other hand, it’s critical for audio players like the iPod app to be able to play even when in vibrate mode. So, how do we go about changing our session category and getting those mysteriously absent route change callbacks? Like so:
1 2 | |
This tells the AudioSession that we want to be regarded as a ”media playback” app, rather than, for example, an “ambient sound” app. Now, regardless of the position of the vibrate switch, we get notifications when our iPhone is docked and undocked from external accessories, and we can animate our volume controls as we desired.