
AccessibilityService는 기본적으로 장애가 있는 사용자가 안드로이드 기기 및 앱을 사용하는 것을 돕기 위해 설계되었습니다. 이 서비스는 백그라운드에서 실행되며, 사용자 인터페이스의 상태 변화가 발생할 때 Android Framework의 시스템 프로세스인 system_server로부터 콜백을 전달받습니다. 이때 AccessibilityEvent가 발생하며 시스템과 통신하게 됩니다.
ㅤ

접근성 서비스의 생명주기는 시스템에 의해 독점적으로 관리되며 표준 서비스 생명주기를 따릅니다.
시작 : 사용자가 설정에서 서비스를 명시적으로 켰을 때, 즉 사용자에 의해서만 트리거됩니다. 이후 시스템이 서비스에 바인딩되면 onServiceConnected()가 호출됩니다.
종료 : 사용자가 설정에서 직접 서비스를 끄거나, 서비스 내부에서 AccessibilityService.disableSelf()를 호출할 때 종료됩니다.
보안 : AndroidManifest.xml 선언 시 BIND_ACCESSIBILITY_SERVICE 권한을 요청해야 합니다. 이는 오직 시스템만이 해당 서비스에 바인딩할 수 있도록 보장하기 위함입니다.
ㅤ

AccessibilityService를 사용하기 위해서는 AndroidManifest.xml에 다른 서비스처럼 등록해야 하지만, 반드시 다음 두 가지 사항을 준수해야 합니다.
ㅤ

서비스가 시스템에 어떻게, 그리고 언제 실행될지 알려주기 위해 다음과 같은 구성 변수들을 고려해야 합니다.
이벤트 응답 : 서비스가 어떠한 이벤트 유형에 응답하고 반응할 것인지 결정해야 합니다.
활성화 범위 : 서비스가 모든 앱에 대해 활성화되어야 하는지, 혹은 특정 패키지 명칭을 가진 앱에서만 동작해야 하는지 설정합니다.
피드백 방식 : 서비스가 사용자에게 제공할 서로 다른 피드백 유형(음성, 진동 등)이 무엇인지 지정합니다.

서비스가 특정 유형의 접근성 이벤트를 수신하도록 설정하는 데는 두 가지 방법이 있습니다.
ㅤ

먼저 XML 파일을 사용하여 서비스를 구성하는 것입니다. canRetrieveWindowContent와 같은 특정 구성 옵션은 XML을 사용하여 서비스를 구성하는 경우에만 사용할 수 있습니다.
XML 파일을 가리키는 meta-data 태그를 매니페스트에서의 접근성서비스 선언에 추가합니다.
ㅤ

setServiceInfo()를 호출하여 언제든지 동적으로 서비스 구성을 변경할 수 있습니다.
이는 onServiceConnected() 메서드를 오버라이드하여 설정할 수 있습니다.
ㅤ

접근성 서비스는 AccessibilityService 클래스를 확장하고 특정 메서드들을 오버라이드해야 합니다. 이 메서드들은 안드로이드 시스템이 호출하는 순서에 따라 나열됩니다.
서비스 시작 시 : onServiceConnected()
실행 중 : onAccessibilityEvent(), onInterrupt()
종료 시 : onUnbind()
onServiceConnected() (선택 사항)
시스템이 사용자의 접근성 서비스에 연결될 때 이 메서드를 호출합니다.
서비스를 위한 일회성 설정(one-time setup) 단계를 수행하는 데 사용됩니다.
onAccessibilityEvent() (필수 사항)
서비스에 지정된 이벤트 필터링 매개변수와 일치하는 AccessibilityEvent를 시스템이 감지하면 이 메서드를 호출합니다.
시스템이 이 메서드를 호출할 때 관련 AccessibilityEvent를 전달하며, 서비스는 이를 해석하여 사용자에게 피드백을 제공합니다.
서비스의 수명 주기 동안 여러 번 호출될 수 있습니다.
onInterrupt() (필수 사항)
시스템이 서비스가 제공 중인 피드백을 중단(interrupt)하고자 할 때 이 메서드를 호출합니다.
마찬가지로 서비스 수명 주기 동안 여러 번 호출될 수 있습니다.
onUnbind() (선택 사항)
시스템이 접근성 서비스를 종료하려고 할 때 이 메서드를 호출합니다.
리소스 해제 등 일회성 종료 절차를 수행하는 데 사용됩니다.
ㅤ

접근성 서비스 설정의 가장 중요한 기능 중 하나는 서비스가 처리할 수 있는 접근성 이벤트의 유형을 지정하는 것입니다. 이 정보를 구체적으로 지정함으로써 여러 접근성 서비스가 서로 협력할 수 있으며, 특정 앱의 특정 이벤트 유형만 처리할 수 있는 유연성을 갖게 됩니다.
패키지 이름 (Package names)
서비스가 처리하고자 하는 앱의 패키지 이름을 지정합니다.
정적 방식 : XML 설정 파일에서 android:packageNames 속성에 쉼표로 구분된 목록을 작성합니다.
동적 방식 : 코드 내에서 AccessibilityServiceInfo.packageNames 멤버를 사용합니다.
이 매개변수를 생략하면, 서비스는 모든 앱의 접근성 이벤트에 대해 사용 가능한 것으로 간주됩니다.
이벤트 유형 (Event types)
서비스가 처리하기를 원하는 접근성 이벤트의 유형을 지정합니다.
정적 방식 : XML 파일에서 android:accessibilityEventTypes 속성을 사용하며, | 문자로 이벤트를 구분합니다 (예: typeViewClicked|typeViewFocused).
동적 방식 : 코드 내에서 AccessibilityServiceInfo.eventTypes 멤버를 통해 설정할 수 있습니다.
ㅤ

서비스는 화면의 구조를 파악하고 그 위에 시각적 요소를 추가할 수 있습니다.
화면 탐색 : 화면 콘텐츠는 AccessibilityWindowInfo 및 AccessibilityNodeInfo 객체의 트리 구조로 표현됩니다. 이 기능을 사용하려면 SERVICE_META_DATA가 참조하는 XML 리소스를 통한 설정이 반드시 필요합니다.
주의사항 : 서비스가 노드 계층 구조가 변경되었음을 인지하지 못할 수 있으며, 윈도우 콘텐츠는 언제든지 변경될 수 있음으로 인해 오래된 정보를 가질 가능성이 있습니다.
ㅤ

접근성 오버레이의 역할 및 활용
AccessibilityService는 Android Framework의 시스템 프로세스인 system_server와의 상호작용을 통해 기존 화면 콘텐츠 위에 오버레이를 그릴 수 있습니다. 이 기능은 주로 화면의 아이템을 시각적으로 강조하거나, 사용자가 서비스와 직접 상호작용할 수 있는 방법을 제공하여 서비스의 동작을 커스텀하는 데 사용됩니다.
오버레이 부착 방식 및 위치 제어
오버레이는 목적에 따라 특정 윈도우 또는 디스플레이 자체에 부착할 수 있습니다.
윈도우에 부착된 오버레이는 윈도우가 움직이거나 크기가 변해도 그 안에서 동일한 상대적 위치를 유지하합니다.
디스플레이에 부착된 오버레이는 해당 디스플레이의 활성 윈도우와 독립적으로 존재합니다. 특정 UI 요소의 위치에 오버레이를 정확히 배치하기 위해서는 AccessibilityNodeInfo.getBoundsInWindow를 호출하여 윈도우 좌표 기준의 경계값을 구해야 합니다.
ㅤ

성능 최적화를 위해 이벤트 전달 속도를 제어해야 합니다.
이벤트 생성은 비용이 큰 프로세스 간 통신(IPC)을 통해 이루어집니다.
따라서 timeout 설정을 활용하여 이벤트가 클라이언트에 너무 빈번하게 전달되는 것을 방지하는 것이 중요합니다.
ㅤ