Kotlin

[Kotlin] Android <-> Javascript 데이터 전송하기

eulBlue 2024. 3. 19. 18:43

📱테스트 환경

Samsung Galaxy Tab Advanced2


와 진짜 .. 이것때문에 몇일동안 크롤링만 한것 같다.

구글에 있는 블로그 글이랑 스택오버플로우 안본게 없는 것 같다 ㅋㅋ

다들 된다고 하지만 나는 안돼서 진짜 너무 우울하고 슬픈 와중에 겨우 해냈는데 다른사람들도 나처럼 시행착오를

겪었을 때 도움이 되거나 내가 나중에 또 다시 볼 수 있도록 기록을 하려고 한다.

START !

Javascript 에서 Kotlin 함수 호출
@JavascriptInterface
fun getOS(): String? {
    return System.getProperty("os.name")
}
webView.addJavascriptInterface(WebAppBridge(context), "AppAPI")
@JavascriptInterface

간단하게 OS 정보를 호출하는 코드를 작성해보자.

중요한건 @JavascriptInterface 인데 이걸 붙이고 함수를 선언하면 자바스크립트에서 호출이 가능해진다.

이렇게 하고 자바스크립트쪽에서는

AppAPI.getOsVersion()

이런식으로 호출하면 정상적으로 데이터를 가져올 수 있는 걸 확인할 수 있다.

Kotlin 에서 Javascript 함수 호출

이게 진짜 문제였는데 .. 나는 아무리 남들이 다 사용하는

loadUrl
evaluateJavascript

사용해도 함수가 호출이안되더라 .. 문제는 에러도 발생하지않아서 원인이 뭔지도 모르겠어서 너무 답답했다.

심지어는 자바스크립트쪽 함수를 지워버려도 에러도없이 그냥 지나가지더라 ..

이를 해결 하기 위해서 열심히 찾아보니까 evaluateJavascript 사용법을 잘 몰랐고

dispatchEvent 를 사용했는데

webView.evaluateJavascript("window.dispatchEvent(new CustomEvent('AOSFunction', {detail: 'Hello World!'}))", null)

evaluateJavascript 뒤에 null 을 넣으면 callback 이 없다는 뜻이다. 콜백함수가 필요하다면 null 을 제거하고

함수로 만들어주면 정상적으로 작동한다.

자바스크립트쪽에는

// nuxt

onMounted(async () => {
  console.log('onMounted', menuList)
  window.addEventListener("AOSFunction", AosToWeb);

  await nextTick(() => {
    cateList()
    optionList()
  })
})
onUnmounted(() => {
  console.log('onUnmounted')

  // 이벤트 리스너 정리
  window.removeEventListener("AOSFunction", AosToWeb);
})

Mounted 될 때 함수를 등록해주고

const getAosImage = (e: any) => {
  try {
    console.log(e.detail)
  } catch (e) {
    console.log(e)
  }
}

e.detail 을 찍어보면 전송한 데이터를 확인할 수 있다.

시행착오 1

evaluateJavascript  를 사용할 때 아무런 반응이없어서 원인을 찾기 힘들었는데 callback 함수를 등록해도, 안해도

반응이 없으니 너무 답답한 상황.

webView.evaluateJavascript("window.dispatchEvent(new CustomEvent('AOSFunction', {detail: 'Hello World!'}))", null)

or

webView.evaluateJavascript("window.dispatchEvent(new CustomEvent('AOSFunction', {detail: '$image'}))", null)

of
(false)
webView.evaluateJavascript("window.dispatchEvent(new CustomEvent('AOSFunction', {detail: base64/~'$image'}))", null)

 

 

이런식으로 데이터를 보내줘야지 세번째 처럼 디테일 안에 문자열과 함께 묶어서 보내주니까 반응이 없었다.

알고보니까 싱글 쿼테이션 안에 넣어주지 않아서긴 한데 문자열로 어차피 취급받으니까 문제 없을거라고

생각한 안일함이 문제였다.

시행착오 2

다른사람들 evaluateJavascript loadUrl 을 사용한걸 보면

evaluateJavascript 사용할때는

evaluateJavascript("function()", null)

loadUrl 사용할때는

loadUrl("javascript:function()")

이런식으로 사용하던데 나는 아무런 효과를 보지 못했다.

에러가 발생하거나 반응도 없었기 때문에 원인을 파악하지는 못했지만 .. 위에 작성한 내용으로만 반응이 있었기에

저대로 헀는데 그래도 해결할 수 있어서 다행이다.

 

마지막으로 내가 정말 많은 스택오버플로우와 블로그 글들을 봤지만 진짜 큰 도움을 준 블로그 두 개가 있어서

함께 참고해보면 정말 좋을 것 같다. [ 감사의 인사 ]

[Medium] galcyurio 님

https://medium.com/prnd/%EC%9B%B9%EC%97%90%EC%84%9C-%ED%8C%8C%EC%9D%BC-%EC%84%A0%ED%83%9D%ED%95%98%EA%B8%B0-onshowfilechooser-%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EB%8B%A8%EC%9D%BC-%EB%B0%8F-%EB%B3%B5%EC%88%98-%ED%8C%8C%EC%9D%BC-%EC%84%A0%ED%83%9D-%EB%B0%A9%EB%B2%95-b2553726b06e

[티스토리] 아는만큼 보이고, 보이는 만큼 모자른 것을 알게 된다.

https://gradler.tistory.com/32

 

하이브리드앱(Android-Javascript) 간 인터페이스 방법

Android WebView에서 Local/Remote 환경에 있는 Javascript와 인터페이스 하는 방식에 대해 간략히 살펴보겠습니다. 유사한 내용을 정리한 글은 찾아보면 많이 있지만 대부분 한 쪽 측면(웹 또는 네이티브

gradler.tistory.com