| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
| 29 | 30 | 31 |
- Realm
- Swipe Gesture
- 정보처리기사
- AVFoundation
- liquid glass style
- parse
- 정보처리기사 실기
- Codable
- swift
- ios카메라유선연결
- UITableViewCell dynamic height
- UITableView
- Decodable
- uikit
- 정보처리기사 실기 요약본
- CustomCode
- libxlsxwriter
- JSON
- JSONParser
- 소프트 키보드
- Pod
- ios 26
- usb카메라연결
- cocoapods
- avcapturesession
- Xcode
- ios외부디바이스연결
- UITableViewCell 동적높이
- IOS
- ios외부카메라연결
- Today
- Total
iOS 개발일기
[AOS] USB 연결 시 사라지는 소프트 키보드 되찾기 본문
요즘 안드로이드 프로젝트 개발을 진행 중이다... 현재 진행하고 있는 프로젝트는 하드웨어를 연동 및 통신을 하는데 iOS에서 경험해본 터라 하드웨어와 관련된 개발은 크게 어렵지는 않았다. 그동안 안드로이드는 유지보수 위주로 다뤄왔기에, 새로운 기능 개발은 처음이었다. 그래서인지 코드 보다는 OS 환경에 대한 지식이 부족한 탓에 하드웨어와 관련된 기능에만 몰두하며 테스트를 이어가고 있었다.
그러다 테스트 도중, 블루투스 때는 없었던 기괴한 현상이 발생하는데 USB만 꽂으면 화면에서 소프트 키보드가 가출해버리는 문제였다.
이류를 좀 찾아보니, 안드로이드가 해당 하드웨어를 HID(Human Interface Device) 프로필로 인식하는 것이 원인이었다. 시스템이 연결된 기기를 '외부 키보드'로 간주하면서, '넌 키보드 연결했으니까 내가 화면 잘 보이게 소프트 키보드 없앨게'라고 해버린 것이다.
HID(Human Interface Device) Profile이란?
키보드, 마우스, 게임패드처럼 사람이 컴퓨터에 직접 입력 또는 출력을 받는 주변 기기를 연결하기 위한 표준 프로토콜이다.
근데 왜 뜬금없이 이 리더기는 HID로 인식되었을까?
한 마디로 '범용성' 때문이라고 한다. HID는 전 세계가 약속한 규격이기에 별도의 드라이버 설치 없이 어디서든 즉시 작동한다.
만약 HID가 아닌 다른 통신 방식을 사용했다면, 사용자는 기기를 연결할 때마다 전용 드라이버를 찾아 설치해야 하는 불편함을 감수해야 된다.
뭐 이런저런 이유를 알아보고 납득 후에 이 문제에 대해서 해결하려고 해결방법을 찾아보는데, 옛날 글들은 제어를 할 수 있다고 알려주고 그걸 적용해보면 하나도 안먹히는 것이다.
그래서 좀 더 찾아보니(AI가 알려준 코드도 안먹혀서 구글링까지 간것...)
안드로이드 9.0(Pie) 버전 이상 부터는 보안 강화를 위해 HID 서비스 접근을 금지하여 현재 코드상으로 소프트 키보드를 제어하는 것이 불가능하다는 것을 알알았다.
이걸 어떻게 해결할까 고민을 하다가
HID 장치가 연결이 되어 있어도 소프트 키보드를 표시할 수 있는 방법이 OS 설정에 있다는 것을 알았다.
[설정 → 하드웨어 키보드 → 스크린 키보드 표시] 옵션을 활성화 해주면 USB 리더기를 연결해도 소프트 키보드가 표시가 된다.
여기까지 하고나서 이렇게 쉽게 해결되는 거구나 쉽게 생각하고 테스트를 막 해보는데
이 옵션을 설정하니 또 이상한 문제가 발생한 것이다.
기존 프로젝트는 소프트 키보드를 내리더라도 EditText에 포커스를 해제하지 않았었다. 딱히 해제를 하지 않아도 평소에는 문제없었는데,
스크린 키보드를 설정을 통해 강제로 표시했을 때에는 조금 달랐다.
EditText에서 포커스를 해제하지 않은 상태로 다른 화면이나 동작을 할 때마다 소프트 키보드가 화면에 표시되는 것이었다.
그래서 키보드를 사용하지 않을 때에는 무조건 포커스를 해제 시켜줘야하는 로직을 추가하기로 했다.
다행히 EditText가 사용되는 곳들은 BaseActivity를 상속받기 때문에 한 곳에서 다 처리할 수 있었다.
보통 안드로이드에서는 키보드를 내려도 EditText에 포커스가 남아있는데, 이 포커스를 해제시키기 위해 onCreate에 추가를 해준다.
private void setupKeyboardDismiss() {
ViewCompat.setOnApplyWindowInsetsListener(getWindow().getDecorView(), (v, insets) -> {
// 화면에 소프트 키보드가 보이는 상태인지 확인
if (!insets.isVisible(WindowInsetsCompat.Type.ime())) {
View focused = getCurrentFocus();
if (focused instanceof EditText) {
focused.clearFocus();
}
}
return ViewCompat.onApplyWindowInsets(v, insets);
});
}
이 메서드를 추가하고 테스트를 해보고 단순히 키보드를 내리는 동작(뒤로가기 및 키보드 내리기)에 대해서는 잘 동작하지만
소프트 키보드가 살아있는 상태에서 어떠한 사용자 동작에 의해 다른 화면이 표시되거나 이동하게 될 경우 키보드의 포커스가 살아있는 바람에 키보드가 계속 표시되는 문제가 또 있었다.
이 문제를 또 해결하기 위해 'onWindowFocusChanged'라는 메서드를 찾았다. 이 메서드는 현재 Activity가 포커스인가 아닌가를 알 수 있다.
@override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hansFocus);
if (!hasFocus) hideKeyboard();
}
public void hideKeyboard() {
View focused = getCurrentFocus();
if (!(focused instanceof EditText)) return;
// Edge-to-Edge 모드가 기본으로 적용되어 있어야 가능
WindowInsetsController controller = focused.getWindowInsetsController();
if (controller != null) {
controller.hide(WindowInsets.Type.ime());
}
}
여기서 주의해야될게 있다. 안드로이드의 'Edge-to-Edge' 속성을 사용하지 않으면 해당 메서드는 사용할 수 없으므로 주의해야 한다.
(안드로이드 15 이상에서는 기본이지만, 미만 버전에서는 속성을 적용해주어야 한다.)
시나리오 테스트 중 [소프트 키보드 표시 → 포커스 활성화 상태→ 사이드 바 화면 표시] 이 시나리오에서는 'onWindowFocusChanged' 메서드가 호출되지 않고 키보드가 화면에 떡하니 떠있었다.
왜? 왜 사이드 바가 화면에 표시될 때에는 키보드가 사라지지 않았을까? 코드를 파악해보니
사이드 바는 Activity나 Fragment가 아니라 View로 되어 있어서 호출되지 않는 것이었다.
원인을 파악하고 난 후에는 이걸 어떻게 해결해야될까 고민을 좀 하게 되었는데, 가장 간단한게 이 뷰를 호출할 때에 'hideKeyboard' 메서드를 호출하는게 가장 깔끔한 것 같아 View가 화면에 표시될 때에 호출하여 키보드 포커스를 해제하여 해결했다.