개요
AudioFocus가 적용되어 있지 않은 애플리케이션에 AudioFocus를 적용해야만 하는 일이 생겼다. 지금까지는 쓸 일도, 그럴 필요도 없었기에 이 친구의 존재를 모르고 있었는데 적용할 일이 생겼으니 공부해 보자 싶었다. 이번 포스팅에서는 AudioFocus를 왜 써야 하는지, 그리고 어떻게 사용해야 하는지에 대해 적어보려고 한다.
AudioFocus가 뭐야?
Android OS에게 “나 지금 미디어 필요해! 쓴다!” 하고 통보하는 기능으로, 일종의 약속이다. AudioFocus를 요청할 때에는 어떤 용도로 오디오를 사용하는지에 대한 정보를 함께 전달해야 한다. 용도에 대한 정보는 AudioAttributes
인스턴스 생성 후 setUseage()
와 setContentType()
를 통해 세팅할 수 있으며, 다음의 값 중 하나를 가진다. (번역은 셀프입니다. ㅎㅎ;😉
setUseage List
값 | 설명 |
---|---|
USAGE_UNKNOWN | Usage value to use when the usage is unknown. |
USAGE_MEDIA | Usage value to use when the usage is media, such as music, or movie soundtracks. |
USAGE_VOICE_COMMUNICATION | Usage value to use when the usage is voice communications, such as telephony or VoIP. |
USAGE_VOICE_COMMUNICATION_SIGNALLING | Usage value to use when the usage is in-call signalling, such as wite a “busy” beep, or DTMF tones. |
USAGE_ALARM | Usage value to use when the usage is an alarm (e.g. wake-up alarm). |
USAGE_NOTIFICATION | Usage value to use when the usage is notification. See other notification usages for more specialized uses. |
USAGE_NOTIFICATION_RINGTONE | Usage value to use when the usage is telephony ringtone. |
USAGE_NOTIFICATION_COMMUNICATION_REQUEST | Usage value to use when the usage is a request to enter/end a communication, such as a VoIP communication or video-conference. |
USAGE_NOTIFICATION_COMMUNICATION_INSTANT | Usage value to use when the usage is notification for an “instant” communication such as a chat, or SMS. |
USAGE_NOTIFICATION_COMMUNICATION_DELAYED | Usage value to use when the usage is notification for a non-immediate type of communication such as e-mail. |
USAGE_NOTIFICATION_EVENT | Usage value to use when the usage is to attract the user’s attention, such as a reminder or low battery warning. |
USAGE_ASSISTANCE_ACCESSIBILITY | Usage value to use when the usage is for accessibility, such as with* a screen reader. |
USAGE_ASSISTANCE_NAVIGATION_GUIDANCE | Usage value to use when the usage is driving or navigation directions. |
USAGE_ASSISTANCE_SONIFICATION | Usage value to use when the usage is sonification, such as with user interface sounds. |
USAGE_GAME | Usage value to use when the usage is for game audio. |
USAGE_ASSISTANT | Usage value to use for audio responses to user queries, audio instructions or help utterances. |
setContentType List
값 | 설명 |
---|---|
CONTENT_TYPE_UNKNOWN | Content type value to use when the content type is unknown, or other than the ones defined. |
CONTENT_TYPE_SPEECH | Content type value to use when the content type is speech. |
CONTENT_TYPE_MUSIC | Content type value to use when the content type is music. |
CONTENT_TYPE_MOVIE | Content type value to use when the content type is a soundtrack, typically accompanying a movie or TV program. |
CONTENT_TYPE_SONIFICATION | Content type value to use when the content type is a sound used to accompany a user action, such as a beep or sound effect expressing a key click, or event, such as the type of a sound for a bonus being received in a game. These sounds are mostly synthesized or short Foley sounds. |
AudioFocus를 뺏길 땐 어떻게 해?
Android는 다 계획이 있다, 이 말이야! 이 경우를 대비해서 Listener(AudioManager.OnAudioFocusChangeListener
) 를 제공한다. 개발자는 이 Listener에서 처리할 수 있는 이벤트는 다음과 같다.
AudioFocus Change Listener Event List
Event | 설명 |
---|---|
AUDIOFOCUS_NONE | Used to indicate no audio focus has been gained or lost, or requested. |
AUDIOFOCUS_GAIN | Used to indicate a gain of audio focus, or a request of audio focus, of unknown duration. |
AUDIOFOCUS_GAIN_TRANSIENT | Used to indicate a temporary gain or request of audio focus, anticipated to last a short amount of time. Examples of temporary changes are the playback of driving directions, or an event notification. |
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK | Used to indicate a temporary request of audio focus, anticipated to last a short amount of time, and where it is acceptable for other audio applications to keep playing after having lowered their output level (also referred to as “ducking”). Examples of temporary changes are the playback of driving directions where playback of music in the background is acceptable. |
AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE | Used to indicate a temporary request of audio focus, anticipated to last a short amount of time, during which no other applications, or system components, should play anything. Examples of exclusive and transient audio focus requests are voice memo recording and speech recognition, during which the system shouldn’t play any notifications, and media playback should have paused. |
AUDIOFOCUS_LOSS | Used to indicate a loss of audio focus of unknown duration. |
AUDIOFOCUS_LOSS_TRANSIENT | Used to indicate a transient loss of audio focus. |
AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK | Used to indicate a transient loss of audio focus where the loser of the audio focus can lower its output volume if it wants to continue playing (also referred to as “ducking”), as the new focus owner doesn’t require others to be silent. |
어떻게 사용해?
음, Helper
라는 단어 사용을 지양해야 한다고 하는데 마땅한 단어가 떠오르지 않는다. 그래서 어쩔 수 없이 AudioFocusHelper.java
class를 만들게 되었다. ^^; 필요한 곳에서 AudioFocus
를 context
와 함께 생성한다. 이후, AudioFocus
가 필요할 때 requestAudioFocus()
함수를 호출하면 깔끔하게 완성!
1 | public class AudioFocusHelper implements AudioManager.OnAudioFocusChangeListener { |
마무리하며
필수 요건이 아닌 약속이라고 표현한 이유가 있다. 사실상 AudioFocus
를 요청하지 않아도 사운드 출력에는 문제가 없다. Android 플랫폼 생태계를 무시하고, ‘난 무조건 재생해야 해!’ 라는 억지를 부리고 싶다면 AudioFocus
없이 미디어를 출력해 버리면 된다. 혹은 AUDIOFOCUS_LOSS
이벤트를 받자마자 다시 GAIN하는 방법도 있지만, 당연히 권장하지 않는다.
플랫폼 위에 올라가는 서비스 개발자는 플랫폼의 약속을 이행하는 것이 좋다. 이 자그마한 규약들은 각각의 앱들이 최대한 ‘정상 범주’ 내에서 동작할 수 있도록 만들어졌다. AudioFocus
를 무시하고 재생하는 앱이 하나일 경우에도 문제이지만, 여러 앱이 이것을 무시하고 재생한다면 UX가 와장창 깨지고 말 것이다. 알람도 울리고, 음악도 재생되고, 또 다른 앱에서 게임 소리도 나고, 또 다른 앱에서 영상이 재생되는 등의 복합 상황이 발생할 수 있다. 플랫폼의 약속은, 이런 복합 상황을 어느 정도 Android OS에게 '위임’한다는 의미를 포함한다.