안드로이드 앱 자동화 (상점 스크랩, 도어락 자동화) – 3-2편
※ 이번 편은 모듈 개발의 실패한 케이스로 외전 격으로 봐주시면 되겠네요. ㅋㅋ
[ 3편보기 ]
1. 저번편 에서..
안드로이드 에뮬레이터 게스트머신의 마우스 움직임
을 제어 했었고. 업무 개발 이전에 키보드제어 도 다루어야 할 거 같아서 끼움 편을 만들어 보았다.
키보드나 마우스나.. 처음에는 같은부류라 생각했다. 똑같이 evdev
(event-device
) 이고 통신구조도 거의 대동소이 한 터라 비슷하게 넘어가려 했는데...
2. 그래 세상일이 어디 그렇게 쉽게 되던?
일단 간단하게 키보드 입력 테스트케이스를 만들어 시험해 보았다.
@Test void testKeyboard() throws Exception {
if (!TestUtil.isEnabled("testKeyboard", TestLevel.MANUAL)) { return; }
Commander cmd = null;
try {
/** qmp / adb 를 연결한다. */
cmd = new Commander("172.17.0.1", 4444, "172.17.0.1", 5555);
cmd.sleep(1000);
/** a 부터 d 까지 순차적으로 입력 */
for (char c = 'a'; c <= 'd'; c++) {
cmd.sendKeys(String.valueOf(c), "ret");
cmd.sleep(500);
}
/** a ~ d 까지 한꺼번에 입력 */
cmd.sendKeys("a", "b", "c", "d", "ret");
} finally {
safeclose(cmd);
}
}
훗. 뭐야 잘 되잖아! ㅋ. 괜히걱정했.....
하는 순간 무언가 뇌리를 스쳐갔다.
그런데 한글은?....되.던....가?.......
(한글입력기로 전환하고 한글 입력 위치에 맞는 영문 키보드 입력 데이터를 전송해야.... 하나?)
(사실 한글은 컴퓨터에서 우리가 너무 자연스레 썼지만. raw-device
입장에서는 전혀 자연스럽지 못하다....)
3. ..그래서 시작된 삽질
일단 별도 프로젝트인 ntiple-utils 에 Hangul.java 파일을 만들고
한글을 두,세벌식 키보드로 스크로트 할 수 있는 테이블을 만들었다.
(원래는 다른 목적으로 만든 프로그램 이었다.)
/** 키보드 한글 스트로크 테스트 */
@Test public void testHangulInput() throws Exception {
String test = "한글테스트중입니다";
String kbst = "";
kbst = new String(Hangul.extractkbst(test, Hangul.TB_2BUL));
log.info("두벌식스트로크 {} -> {}", test, kbst);
kbst = new String(Hangul.extractkbst(test, Hangul.TB_3BULF));
log.info("세벌식(최종)스트로크 {} -> {}", test, kbst);
}
/** 키보드 한글 스트로크 안드로이드 입력 테스트 */
@Test void testHangulKeyboard() throws Exception {
if (!TestUtil.isEnabled("testHangulKeyboard", TestLevel.MANUAL)) { return; }
Commander cmd = null;
try {
/** qmp / adb 를 연결한다. */
cmd = new Commander("172.17.0.1", 4444, "172.17.0.1", 5555);
cmd.sleep(1000);
String test = "한글테스트중입니다";
String kbst = new String(Hangul.extractkbst(test, Hangul.TB_2BUL));
for (int inx = 0; inx < kbst.length(); inx++) {
cmd.sendKeys(kbst.substring(inx, inx + 1));
cmd.sleep(500);
}
} finally {
safeclose(cmd);
}
}
실행결과 (testHangulInput
)
두벌식스트로크 한글테스트중입니다 -> gksrmfxptmxmwnddlqslek
세벌식(최종)스트로크 한글테스트중입니다 -> mfskgw'cng'glbajd3hduf
이제 PC 에서 한글 로 맞춰놓고 영문키보드 위치의 gksrmfxptmxmwnddlqslek
를 타이핑 해 보면
한글테스트중입니다
라고 출력될 거다. 안드로이드에서 테스트해 보면.. (testHangulKeyboard
)
로 정상적으로 실행된다... 하지만....
4. 아! 또!! 왜~!!
"문제는 반드시 혼자 오지 않는다!"... 분량상 결과만 말하자면..
-
안드로이드 입력기의 현재 상태파악이 어렵다. (현재 입력기가 한글상태 인지 아닌지 파악 불가)
-
한글 + 영숫자, 특수기호등이 혼용되는 경우 타입별로 분리해서 입력해 주어야 한다.
-
타이밍 문제등(입력기 변환시) 오타가 발생하는경우 대처가 어렵다.
등의 문제로 요약해 볼 수 있겠다..
삽질한게 아깝지만 일단은 다른 방법을 찾아야 겠다.
다행히 stack overflow
를 뒤지다 보니 나와 비슷한걸 하려는 사람이 있었나보다
https://stackoverflow.com/questions/14224549/adb-shell-input-unicode-character
첫번째 답변으로 제시된 ADBKeyboard
를 사용해 보기로 했다.
우선은 AdbKeyboard 를 설치하고 (AdbKeyboard 다운로드)
$ adb -s 127.0.0.1:5555 install ADBKeybaord.apk
Performing Streamed Install
Success
게스트머신에서 입력키보드를 설정해 주어야 한다
시스템 -> 언어 및 입력 -> 가상키보드 -> 키보드관리 -> ADBKeyboard 활성화
그리고 제어기를 구현한다.
/** 키보드입력 문자열 전송(한글 등 유니코드) */
public String inputUniStr(String str) throws Exception {
String term = "";
String ret = "";
for (; str.length() > 0;) {
log.trace("FSTR:{} / {}", str, term);
term = new String(str);
/**
* 프로그램문제인지 간혹 긴문장 전송시 잘린다.
* 해서 안정화 문제로 5글자씩 분할하여 전송한다
**/
if (term.length() > 5) {
term = str.substring(0, 5);
str = str.substring(5);
} else {
str = "";
}
// log.debug("INPUT-UNI:{}", term);
String cmdstr = joinStr(AM, BROADCAST, _A, ADB_INPUT_TEXT, __ES, MSG, dquot(term));
String[] cmdarr = arr(adb, _S, cat(server, ":", port), SHELL, SH, _C, quot(cmdstr));
ret = execRawCmd(rtm, cmdarr, buf);
log.trace("CMD:{}{} / {}", "", cmdarr, ret);
msleep(100);
}
return ret;
}
테스트 케이스 도 구현하고
@Test void testAdbKeyboard() throws Exception {
if (!TestUtil.isEnabled("testAdbKeyboard", TestLevel.MANUAL)) { return; }
Commander cmd = null;
try {
/** qmp / adb 를 연결한다. */
cmd = new Commander("172.17.0.1", 4444, "172.17.0.1", 5555);
/** Adb 입력기로 전환 */
cmd.chImeAdb();
cmd.sleep(300);
cmd.inputUniStr("한글과 English 를 같이 테스트 중입니다.");
cmd.sendKeys("ret");
} finally {
safeclose(cmd);
}
}
실행결과
(너무나도 허무하게...) 아무런 부작용 없이 깔끔하게 잘 된다
5. 결론! (라떼는 말이야...)
어렸을때 대학 강의시간에 교수님께 들었던. 20년도 넘게 지나 아직까지 기억나는 인상적인 말씀이 있었다.
"앞으로는 know-how
보다 know-where
가 중요한 시기가 올것이다."
그 때 당시에는 C언어 알고리즘 같은 know-how
에 열중해 공부하느라 가볍게 들었는데.
실제 IT 프로젝트들에 뛰어들어보니, 내가 구상하고 작성한 것 보다 월등히 뛰어난 코드들이 넘쳐나고 있었다.
그때 당시 그 교수님은 이미 집단지성의 의미를 파악하고 학생들한테 전파했던 듯..
뭐.. 여튼 무언가 바닥부터 만들어야 할 때에는 코딩에 앞서 비슷한게 먼저 구현된 것이 있는지 구글에 검색부터 해 보도록 하자!
이제 다음편은 진짜 진짜!! Work 를 만들어 볼거다!
[ 4편에서 계속 ]
[ Hangul.java 소스 ]
[ Commands.java 소스 ]
[ 관련 소스 저장소 ]