아티클

스크린 리더 사용자를 위한, 안드로이드 네이티브 동영상 플레이어 접근성 구현하기 2부

2021-08-23 10:09:08

안녕하세요, 엔비전스입니다.

안드로이드 접근성을 고려한 비디오 플레이어 1부에서는 Talkback 실행 시 재생 컨트롤 사라지지 않게 하기, 동영상 영역을 Talkback이 실행된 상태에서 이중탭하여 컨트롤을 숨기거나 보일 수 있도록 하기, 시간 조절 커스텀 뷰를 볼륨 키로 시간 조절하기에 대해 함께 살폈습니다. 이번 아티클에서는 시간 조절 커스텀 뷰에 재생시간 정보 읽어주도록 구현하기, 10초 뒤로, 10초 앞으로 등의 기능 구현 시 이중탭했을 때 경과 시간 읽어주도록 하기에 대해 살펴보도록 하겠습니다.

커스텀 슬라이더에 시간 정보 대체 텍스트 구현하기

1부에서 말씀드린 부분까지 구현을 하게 되면 슬라이더에는 아무런 시간 정보가 없으므로 Talkback에서는 단순히 슬라이더라는 정보만 읽게 됩니다. 따라서 화면에 표시되고 있는 시간 정보의 값을 스트링 변수 형태로 실시간 업데이트를 한 다음 이를 대체 텍스트 형태로 추가하면 슬라이더에 포커스 했을 때 시간 정보도 함께 읽게 됩니다.

private String getProgressText() {
  return Util.getStringForTime(formatBuilder, formatter, position);
}

setContentDescription("재생 시간" + "" + getProgressText());

그런데 위와 같이 하게 되면 두 가지 문제가 있습니다. 첫째, 시간 텍스트는 시간에 대한 스트링이 업데이트될 때마다 이에 대한 위치, 즉 포지션 정보를 계속 업데이트하기 때문에 슬라이더에 초점을 두고 있으면 계속 시간 정보를 읽는다는 것입니다. 둘째, 첫 번째 문제를 해결한다 하더라도 슬라이더에 포커스 할 때는 시간 정보를 읽어주지만 볼륨 키를 조절하여 슬라이더를 변경했을 때는 시간을 읽어주지 않는다는 것입니다.

첫 번째 문제는 접근성 초점을 슬라이더에 두고 있을 때에는 시간 정보가 업데이트되지 않도록 하고 초점을 벗어났을 때에만 업데이트 되도록 함으로써 해결이 가능합니다. 웹 접근성의 기술을 가지고 설명하자면 롤링이 되고 있는 배너에 포커스를 두는 경우에는 배너가 롤링되지 않도록 구현하는 것과 같습니다. 이때 사용할 수 있는 메서드가 isAccessibilityFocused() 입니다. 따라서 아래와 같이 조건문 형태로 사용할 수 있습니다.

if ( isAccessibilityFocused() ) {
  setContentDescription("");
};

 

두 번째 문제는 사용자가 볼륨 키를 눌러 시간을 조절했을 때 조절을 완료한 다음 view selected 접근성 이벤트를 강제로 주어서 해결할 수 있습니다. 1부에서 자세히 살폈듯이 우리는 performAccessibilityAction 메서드 안에서 볼륨 키우기 혹은 볼륨 줄이기 키를 눌렀을 때 실행될 동작을 구현했습니다. 여기에 추가적으로 sendAccessibilityEvent 메서드를 함께 추가하면 됩니다.

안드로이드에는 10개가 넘는 많은 접근성 이벤트가 있으며 기본적으로 사용자가 한 손가락 오른쪽 쓸기 제스처를 수행하거나 이중 탭을 하는 등 특정 조건이 성립되면 적절한 접근성 이벤트를 시스템에서 보내줍니다. 그런데 이것과 별개로 sendAccessibilityEvent는 특정 조건에 대해서 개발자가 지정한 접근성 이벤트를 강제로 발생시킬 때 사용합니다. 만약 시간 조절 슬라이더가 SeekBar 클래스, 즉 표준 컨트롤로 구현되었다면 이러한 작업을 하지 않아도 됨은 앞에서 여러 번 설명하였습니다. 따라서 다음 예시와 같이 sendAccessibilityEvent 를 적용할 수 있습니다.

public boolean performAccessibilityAction(int action, @Nullable Bundle args) {
  if (super.performAccessibilityAction(action, args)) {
    return true;
  }
  if (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD) {// 볼륨 줄이기 키 눌렀을 때 동작 정의}
  } else if (action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD) {// 볼륨 키우기 키 눌렀을 때의 동작 정의}
  new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
      sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
    }
  }, 1000);
  return true;
}

참고:

  1. 볼륨키를 눌렀을 때 약 1초 정도 지연한 다음 접근성 이벤트를 발생시킨 이유는 이벤트를 지연하지 않고 바로 보내면 시간 정보를 읽으려고 할 때 다음 초로 넘어가면 이를 제대로 Talkback에서 읽지 못하는 현상이 있기 때문입니다.
  2. 여러 접근성 이벤트 중 TYPE_VIEW_SELECTED는 현재 초점을 맞추고 있는 뷰의 정보가 업데이트되었을 때 이를 읽도록 하는 용도로 사용합니다.

앞으로, 뒤로 이동 버튼을 실행할 때의 접근성 구현

앞으로 감기, 뒤로 감기 등의 UI를 구현한 경우 1부에서 언급한 바와 같이 시간을 이동시키면 이동된 시간에 대해 스크린 리더에서 피드백을 받을 수 있어야 합니다. 이를 위해 우리는 announceForAccessibility 메서드를 사용할 수 있습니다. sendAccessibilityEvent 를 사용하지 않는 이유는 시간 텍스트를 가진 뷰와 앞으로 감기, 뒤로 감기 버튼 뷰가 다르기 때문입니다. 따라서 각 버튼의 클릭 리스너에서 시간 이동 구현과 함께 아래 예시와 같이 경과 시간을 읽을 수 있도록 구현할 수 있겠습니다.

timePosition.announceForAccessibility(timePosition.getText());

참고: 해당 기능 구현시에도 약 0.5초 이상을 지연해 주는 것이 안정적입니다.

팁: onInitializeAccessibilityEvent 사용

앞으로 혹은 뒤로 이동 버튼의 클릭 리스너 안에서 스크린 리더 피드백과 관련된 접근성 기능을 구현해도 되지만 클릭 접근성 이벤트가 발생했을 때 이를 캐치해서 스크린 리더 피드백 접근성 기능을 구현할 수도 있습니다. 사용자가 이중 탭을 하면 클릭 리스너가 있는 경우에 클릭 이벤트가 발생하기 때문이며 Talkback에서 뚜둑 하는 클릭 사운드를 통해서 클릭 이벤트가 발생했음을 알 수 있습니다. 이때 사용할 수 있는 메서드가 onInitializeAccessibilityEvent입니다. 해당 메서드는 특정 접근성 이벤트가 발생하였을 때 무언가의 작업을 구현하는 목적으로 사용할 수 있습니다. 해당 메서드에 대한 자세한 설명은 널리 포럼 팁을 참고합니다.

 

지금까지 2부에 걸쳐 동영상 플레이어에서의 접근성 적용에 대해 함께 생각해 보았습니다. 해당 아티클을 통하여 우리나라에서 조금 더 접근성이 좋은 동영상 플레이어들이 구현되기를 바라봅니다.

댓글 0
댓글을 작성하려면 해주세요.