Handling changes in audio output Android


Handling changes in audio output

https://developer.android.com/guide/topics/media-apps/volume-and-earphones

사용자는 오디오 앱의 볼륨을 컨트롤 가능할 것이라 예상한다. 표준 작용에는 볼륨컨트롤(장치의 버튼이나 손잡이 또는 UI의 슬라이더)을 사용할 기능도 포함하며 사용중인동안 헤드폰과같은 보조장치가 연결끊기든지해서 갑작스럽게 시끄럼게 재생되는 것을 피하기 위해서도 그렇다

볼륨 컨트롤 사용하기

사용자가 게임이나 뮤직 앱에서 볼륨키를 누를 때 볼륨은 변경되어야 하며 노래간에 전환으로 플레이어가 일시정지 될 때도 현 게임위치에 음악이 없는 경우에도 해당된다.

안드로이드는 음악, 알람, 알림, 전화옴, 시스템 사운드, 전화 음량, 그리고 DTMF톤에 대해 구별된 오디오 스트림을 사용한다. 이는 각 스트림의 볼륨을 독립적으로 관리할 수 있게 한다.

기본적으로, 볼륨 컨트롤을 누름으로서 활성 오디오 스트림의 볼륨을 수정한다. 만약 앱이 현재 재생중인게 없다면 볼륨키는 링어 볼륨을 조절한다.

앱이 알람 클락이 아닌 이상 STREAM_MUSIC스트림을 사용해 오디오를 재생한다.

볼륨 컨트롤이 적절한 스트림을 확실히 하기위해 setVolumeControlStream() 을 AudioManager.STREAM_MUSIC을 건낸다.

setVolumeControlStream(AudioManager.STREAM_MUSIC)

이 호출을 앱의 생명주기에서 호출하려면 미디어를 제어하는 액티비티나 프래그먼트의 onResume()에서 호출한다. 이 것은 대상 액티비티나 프래그먼트가 보여지면 볼륨컨트롤을 STREAM_MUSIC 으로 연결한다.

스트림 볼륨 프로그램적 제어

몇몇 상황에서 오디오 스트림을 프로그램적으로 제어할 수 있다. 예를 들어, 앱이 존재하는 UI를 교체할 때 이다. 이는 추천되지 않는데 이유는 안드로이드 AudioManager 는 같은 형식의 모든 오디오 스트림을 섞기 때문이다. 이들 메소드는 스트림을 사용하는 모든 앱의 볼륨을 변경하기 때문이다. 이들을 사용하는 것은 피하기 바란다:
- adjustStreamVolume()
- adjustSuggestedStreamVolume()
- adjustVolume()
- setStreamVolume()
- setStreamSolo()
- setStreamMute()

고정된 볼륨 장치와 작업하기

크롬북과 같은 몇몇 장치는 볼륨 컨트롤은 가지고 있지만 앱이 오디오 스트림의 레벨을 변경하는데 AudioManager를 사용하는 것을 허용하지 않는다. 이들은 고정된 볼륨 장치라고 한다. 이는 isVolumeFixed()를 호출해 고정된 볼륨 장치에서 실행중인지를 확인할 수 있다.

오디오 앱은 같은 스트림에서 재생될 수 있는 다른 앱과의 출력 볼륨과의 균형을 위한 기능을 제공해야 한다. 고정된 볼륨 장치에서 앱은 그 자체적 볼륨 컨트롤에 접속해 아래의 테이블의 적절한 setVolume() 메소드에 연결해야 한다.


PlayerMethod
AudioTrackAudioTrack.setVolume()
MediaPlayerMediaPlayer.setVolume()
ExoPlayerUse SimpleExoPlayer.setVolume() which sets the volume of the underlying AudioTrack.

Don't be noisy

사용자는 안드로이드 장치에서 오디오를 질길 때 많은 대체재가 있다. 대부분은 장치는 빌트인 스피커, 와이어드 헤드셋을 위한 헤드폰 잭, A2DP오디오를 지원하기 위한 블루투스 연결과 같은 것들이다.

헤드셋이 언플러그 되거나 블루투스 장치가 접속종료될 때 오디오 스트림은 자동적으로 빌트인 스피커로 재전달한다. 만약 높은 볼륨에서 음악을 들으면 이는 노이지 서프라이즈가 될 수 있다.

다행히 시스템은 ACTION_AUDIO_BECOMING_NOISY 인텐트를 브로드캐스트 해준다. BroadcastReceiver 를 생성해 이 인텐트에 대해 감지한다. 음악 재생기의 경우 사용자는 보통 재생이 일시정지되기를 원한다. 게임앱에서는 충분히 낮은 볼륨으로 변경해주기를 원한다. 리시버는 다음과 같은 형태가 된다.

private class BecomingNoisyReceiver : BroadcastReceiver() {
  override fun onReceive(context: Context, intent: Intent) {
    if (intent.action == AudioManager.ACTION_AUDIO_BECOMING_NOISY) {
      // 재생 일시정지
    }
  }
}

플레이 백을 시작할 때 리시버를 등록하고 종료할 때 등록제거한다. 만약 이 가이드 처럼 앱을 설계한다면 이들 호출은 미디어 세션 콜백의 onPlay()와 onStop()에 있을 것이다.

private val intentFilter = IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)
private val myNoisyAudioStreamReceiver = BecomingNoisyReceiver()

private val callback = object: MediaSessionCompat.Callback() {
  override fun onPlay() {
    registerReceiver(myNoisyAudioStreamReceiver, intentFilter)
  }
  override fun onStop() {
    unregisterReceiver(myNoisyAudioStreamReceiver)
  }
}



덧글

댓글 입력 영역