고팍스에서 이번에 새로 들어가는 기능이 있는데, WebView 로 띄우는 html 안에다가 텍스트 버튼을 추가해야 했었다. 처음 태스크를 받았을 때 JavascriptInterface 써서 이렇게 저렇게 쉽게 하면 되겠네, 생각을 했었으나 나의 착각이었다. 태스크가 생각보다 복잡했던 이유는 다음과 같다.
1. 네트워크 요청을 통해서 어떠한 리스트를 받아와 해당 리스트에 있는 요소일 경우에만 버튼을 띄워주어야 한다.
2. 리스트의 길이가 크기 때문에 캐싱을 해야한다.
3. 네트워킹, 캐싱 코드는 현재 코드베이스를 disrupt 하면 안된다.
4. 안드로이드 웹뷰 자체의 성능이 좋지 않기 때문에 불필요한 연산을 최소화 해야 한다.
5. html 파일 안에 있는 iframe 내부의 또 다른 html 안의 요소에 버튼을 추가해야 하므로 자바스크립트 지식이 어느정도 필요하다.
6. iframe 이 로드되는 시점과 상위 html 이 로드되는 시점이 다르다.
7. 텍스트 옆에 화살표 아이콘도 존재하는데, 해당 아이콘 또한 iframe 내부에 inject 시켜주어야 한다
...
그래서 결론부터 말하자면 약 5일간 삽질하여서 텍스트 버튼과 아이콘을 추가하였다.
삽질하는데 가장 결정적이었던 원인은 iframe 의 로드 시점과 전체 html 의 로드 시점이 다른데, 그것을 간과하였다는 점. 그리고 iframe 내부의 요소에 접근할때는 다음과 같이 해야한다.
//contentDocument 로 iframe 내부의 html 에 접근해야 한다
var a = document.getElementsByTagName('iframe').contentDocument;
//위에서 불러온 다큐먼트를 통해서 iframe 내부의 DOM 요소에 접근해야 한다
var b = a.getElementsByClassName('left')[0];
//근데 새롭게 만드는 요소는 a 가 아닌 document 객체를 참조하여 만들어야 한다 (?아직도 이해되지 않는다)
var c = document.createElement('div');
c.innerText = "Hello World";
c.className = "my-button";
c.style.position = "absolute";
...
//위에서 불러온 iframe 내부의 DOM에 새롭게 만든 div 를 추가해준다
a.append(c);
아무튼 위와 같이 DOM에 잘못했던 것 뿐만 아니라 계속해서 실수했던 부분이 있는데, 그건 바로 안드로이드 내부에서 자바스크립트 코드를 실행시키는 방식에 관한 것이었다.
안드로이드 특정 버전 이후로는 WebView.loadUrl() 이 아니라 WebView.evaluateJavascript(){ ret -> ... } 함수를 사용해야 했었다. 뿐만 아니라 evaluate 함수 안에 들어가는 Javascript 스트링 값 또한 정확히 형식을 맞춰주지 않으면 계속해서 Invalid Token 에러를 내뱉었다.
WebView.evaluateJavascript(
"javascript:function loadButton(){" +
"var a = document.getElementById('myId');" +
"AndroidJSInterface.printLog(a.innerText);"+
"}" +
"loadButton();"
){
// do something with return value
}
object AndroidJSInterface{
@JavascriptInterface
fun printLog(msg : String){
Log.d(TAG, msg)
}
}
위와 같이 정확히 세미콜론을 지켜주어야 했고, 마지막에 반드시 함수를 호출해 주어야만 돌아갔다 ^^ ...
정말 많은 블로그들을 보면서 삽질을 했는데, 결국 알아내어서 정말 기뻤다.
그리고 마지막으로 약간의 삽질을 한 부분은 아이콘을 삽입하는 과정이었다. 처음에는 bootstrap 을 써서 아이콘을 동적으로 불러오는 방식을 생각했으나, 생각처럼 head 에 스크립트를 추가하는게 되지 않았다. 그래서 결국 base64 String 으로 이미지의 src 에 넣어주어서 띄우는 방식으로 진행했다.근데 base64 로 변환해서 열심히 넣어줘도 뜨지를 않네 ? ... 문제는 base64 String 을 utf-8 로 인코딩 해주지 않은데에 있었다 ^^ 빨리 알아내서 다행이었다 ... 이번 배포때 결국 못들어갈 거 같다고 다음에 들어가는 걸로 미루어졌다. 마음이 살짝 아팠지만 뭐 .. 그래도 잘 돌아가서 다행이다 ㅠㅠ
- 이상 미토콘드리아의 삽질기 ...
'Android' 카테고리의 다른 글
3. Kotlin Coroutine - Concurrency issues (0) | 2024.05.15 |
---|---|
2. Kotlin Coroutine - Structured Concurrency, viewModelScope, coroutineScope (0) | 2024.05.15 |
1. Kotlin Coroutine - suspend, resume, Dispatchers. (0) | 2024.05.15 |
[Compose] Compose Phases (0) | 2024.04.29 |
멜론 UI 에 대한 나의 생각 (0) | 2022.01.26 |