getSystemService(), Framework Managers 관련

haehyunlee·2023년 6월 25일

API 레벨

Build.VERSION.SDK_INT : 앱이 실행되는 기기의 API 레벨

  • 안드로이드 버전에 따라 추가/대체되는 기능이 많음.
  • 앱은 하나인데, 사용자 기기의 안드로이드 버전은 통일되지 않고 다양함.
    이러한 이유탓에 앱 측에서 '기기에 상관없이 일괄된 동작을 수행할 수 있도록' 호화성(compatibility)를 고려해 개발해야 한다.

퍼미션

  • 앱의 특정 기능에 부여하는 접근 권한.
  • 내가 개발하는 앱이 다른 앱이나 안드로이드 시스템에서 보호하는 특정 기능을 이용할 때 퍼미션 사용을 설정해야 한다.
  • 반대로 다른 앱에서 내가 만든 기능을 사용할 수 없도록 보호하고 권한을 얻은 앱에만 허용하고 싶을 때 설정한다.

getSystemService()

  • 시스템 서비스를 얻기 위한 안드로이드 Context의 멤버 함수
  • Context 클래스의 인스턴스에서 호출되며, 해당 시스템 서비스의 식별자를 배개변수로 전달받는다. 함수를 호출함으로써 다양한 시스템 서비스를 얻을 수 있다.
  • getSystemService() 함수의 반환형이 Any?이므로, 이를 적절한 _Manager 타입으로 캐스팅해서 변수에 할당해야 한다.
  • 메인 코드를 작성하는 MainActivity 클래스는 말 그대로 Activity이며, Activity 클래스는 Context 클래스를 상속받기 때문에 메인 코드 내에서 Context의 멤버변수 및 함수를 자유롭게 호출할 수 있다.

NONTIFICATION_SERVICE

NOTIFICATION_SERVICE 매개변수를 사용하여 NotificationManger 객체를 얻을 수 있다. 이를 통해 푸시 알림을 생성, 관리 및 제어할 수 있다.

NotificationManager 클래스의 실제 내부 구현은 안드로이드 프레임워크의 일부로, 공개적으로 확인할 수 없으며 어차피 개발자는 notify() 처럼 외부로 공개된 함수 시그니처만 알면 알림을 발행할 수 있기 때문에 내부 코드는 알 필요가 없다.

class NotificationManager {
	// 특정 알림을 생성하거나 업데이트하는 함수
	// id: 알림 식별자, notification: 표시할 알림 객체
	fun notify(id: Int, notification: Notification)
}

안드로이드 플랫폼 아키텍처 - Managers

⭐ 이렇게 번거롭게 시스템 서비스를 얻어야 하는 이유는 원래 상태 바는 시스템에서 관리하는 곳이며 앱이 직접 제어할 수 없기 때문이다. 대신 시스템 측에서 알림을 위해 제공하는 API를 앱에서 이용해 시스템에 알림 기능을 실행하도록 의뢰할 수 있다. 이렇듯 getSystemService()와 관련된 기능들은 모두 알림, 키보드와 같이 내가 개발하는 앱의 단독 기능이 아니라, 안드로이드 OS에 이미 구현되어 있는 기능들이다. Manager 라는 이름에서 알 수 있듯이 NotificationManager, InputMethodManager 등은 전부 기능을 관리하기 위한 매니저 클래스다.

RecyclerView의 Adapter를 갱신할 때,

val adapter = activityMainBinding.recyclerView.adapter as RecyclerViewAdapter
adapter.notifyDatasetChanged()

와 같이 내 화면에 이미 존재하는 RecyclerView의 Adapter를 가져와 형변환 후 함수를 호출하듯이 => 이미 시스템에 존재하는 서비스를 가져와 프로그래밍에 쓸 수 있는 타입으로 형변환한 후 함수를 호출한다.

INPUT_METHOD_SERVICE

INPUT_METHOD_SERVICE 매개변수를 사용하여 InputMethodManager객체를 얻을 수 있다. 이를 통해 키보드 및 입력 방법 관련 작업을 처리할 수 있다.

class InputMethodManager {
	// 키보드 표시
	fun showSoftInput(view: View, flags: Int): Boolean {}
    // 키보드 숨김
    fun hideInputFromWindow(windowToken, IBinder, flags: Int): Boolean {}
}

키보드 표시

val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.showSoftInput(currentFocus, 0)
  • getSystemService() : 입력 메서드 관리자(InputMethodManager) 얻기
  • currentFocus : 현재 포커스를 가진 뷰.
  • view : 키보드를 연결할 뷰. EditText, TextView와 같은 입력 필드가 해당된다.
  • flag : 일반적으로 0을 전달해 기본 동작을 사용한다.
  • 레이아웃이 다 그려지기도 전에 키보드를 올리는 코드가 실행되면 해당 동작은 무시됨. thread를 만들어서 레이아웃이 다 그려지기를 기다렸다가 키보드를 올려야 한다. (보통 500ms)

키보드 숨기기

val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(currentFocus!!.windowToken, 0)
  • currentFocus : 현재 포커스를 가진 뷰. !!는 현재 포커스가 null이 아님을 단언하는 Not-null 연산자. 포커스가 null일 경우 예외 발생.
  • hideSoftInputFormWindow()함수는 포커스를 가진 뷰에서만 소프트 키보드를 숨길 수 있기 때문에, 키보드를 숨기려는 뷰는 포커스를 가지고 있어야 한다.

그 외 서비스

안드로이드에서는 다양한 시스템 서비스(앱이 아니라 시스템 OS 단계에서 제공되는 기능)가 제공되며, getSystemService() 함수를 사용하여 해당 서비스의 인스턴스를 얻을 수 있다. 이렇게 얻은 서비스 인스턴스를 사용하여 해당 서비스와 관련된 작업을 수행할 수 있다.

  • AUDIO_SERVICE : 오디오
  • VIBRATOR_SERVICE : 진동
  • LOCATION_SERVICE : 위치
  • POWER_SERVICE : 전원
  • TELEPHONY_SERVICE : 통신
profile
안드로이드 개발자

0개의 댓글