안녕하세요. 이전 포스팅에 이어 웹뷰에 대해 계속 알아보겠습니다. 이전엔 웹뷰를 생성하여 페이지를 로드하는 것 까지 해봤다면, 이번 글에서는 앱에서 웹뷰에 접근하고 제어하는 기능에 대해 알아보겠습니다.
- 응용프로그램 제어(WebViewClient)
- 페이지의 방문 기록 탐색
- 구성 변경 처리
- 기타 제어
웹뷰를 생성하는 부분은 (1)번 포스팅을 참고하시기 바랍니다.
2022.12.26 - [안드로이드 Android] - [Android] 안드로이드 웹뷰(WebView)(1) - 앱 브라우저에서 호출
응용프로그램 제어
웹뷰에서 웹페이지를 호출할 때 웹 페이지에 의존하여 모든 동작과 제어를 맡길 수도 있지만, 앱에서 웹페이지에 접근하고 페이지의 생성소멸 상태를 인지하기 위해서는 WebViewClient의 메서드를 재정의 해야합니다.
shouldOverrideUrlLoading
val webViewClient: WebViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(
view: WebView?,
request: WebResourceRequest?
): Boolean {
Log.d("TAG_WebView", "shouldOverrideUrlLoading")
return super.shouldOverrideUrlLoading(view, request)
}
…
}
먼저 웹뷰의 페이지가 바뀌었을 때 호출되는 함수입니다.
만약 버전별 대응을 위해 함수를 여러번 호출하게 된다면 return 값을 super 키워드가 아닌 true를 반환하여 중복호출을 막아주시면 됩니다.
onReceiveError
override fun onReceivedError(
view: WebView?,
request: WebResourceRequest?,
error: WebResourceError?
) {
super.onReceivedError(view, request, error)
// 페이지를 불러오는 도중 에러가 발생하면 기록삭제 후 빈 화면 로드
Log.d("TAG_WebView","onReceivedError")
view?.loadUrl("about:blank")
view?.clearHistory()
}
페이지를 로드하는 도중 에러가 발생하면 호출되는 함수입니다. 스택된 히스토리를 초기화하고 빈 페이지를 호출하게 하였습니다.
onPageStarted
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
urlTitle.text = url
Log.d("TAG_WebView","onPageStarted")
}
페이지 로드가 시작될 때 호출되는 함수입니다.
비즈니스 로직에 대한 처리 혹은 캐시나 쿠키 데이터에 대한 처리에 자주 사용됩니다.
onPageFinished
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
Log.d("TAG_WebView","onPageFinished")
}
페이지 로드가 끝나면 호출되는 함수입니다.
doUpdateVisitedHistory
override fun doUpdateVisitedHistory(view: WebView?, url: String?, isReload: Boolean) {
super.doUpdateVisitedHistory(view, url, isReload)
Log.d("TAG_WebView","doUpdateVisitedHistory")
}
위의 함수들을 불러왔음에도 불구하고 호출되지 않는 경우가 있을 수 있습니다.
이는 웹페이지가 SPA(Single Page Application)로 구성되어 있냐, MPA(Multiple Page Application)로 구성되어 있냐에 따라 달라집니다.
만약 SPA로 구성되어 있다면 페이지의 이동이 아닌 랜더링의 변화로 구성이 변경되기 때문에 shouldOverrideUrlLoading이 호출되지 않을 수 있습니다. 이 땐 doUpdateVisitedHistory를 overriding하여 페이지의 랜더링이 리로드 되었는지 (히스토리가 갱신 되었는지) 를 확인할 수 있습니다.
페이지 방문기록 탐색
웹뷰는 자동으로 웹페이지에 접근한 기록이 저장됩니다.
goBack() 메서드로 이전 페이지로 이동 할 수 있으며, goForward() 메서드로 다음 페이지로 이동 할 수 있습니다.
또한, canGoBack() 과 canGoForward() 메서드로 저장된 이전 혹은 다음 페이지가 존재하는지 여부를 알 수 있습니다.
val back: ImageView = findViewById(R.id.webViewBackIv)
back.setOnClickListener() {
if (webView.canGoBack()) // 저장 된 이전 페이지가 있는지 확인
webView.goBack() // 이전 페이지 로딩
else
finish()
}
val forward: ImageView = findViewById(R.id.webViewForwardIv)
forward.setOnClickListener() {
if (webView.canGoForward()) // 저장 된 다음 페이지가 있는지 확인
webView.goForward() // 다음 페이지 로딩
}
구성 변경 처리
안드로이드는 멀티 윈도우 모드를 사용하거나 윈도우를 회전하는 경우 onDestroy()가 호출된 후 onCreate()가 다시 호출됩니다. 그럼 웹뷰가 페이지를 다시 로딩하게 되는데 이 현상을 방지하기 위해 configChanges 속성을 사용하여 구성 변경 도중 객체를 보존 할 수 있습니다.
AndroidManifest.xml
<activity android:name=".MyActivity"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
android:label="@string/app_name">
이 속성은 화면의 방향성 혹은 크기, 트리거, 키보드 가용성의 변화 등을 감지하여 페이지의 재시작을 막아줍니다.
기타 제어
화면 새로고침 - reload()
val refresh: ImageView = findViewById(R.id.webViewRefreshIv)
refresh.setOnClickListener() {
webView.reload()
}
스크롤 맨 위로 올리기 - scrollTo(int, int)
val upScroll: ImageView = findViewById(R.id.webViewUpIv)
upScroll.setOnClickListener() {
webView.scrollTo(0, 0) // (x , y)
}
+ 2023-09-18 추가 :
페이지의 맨 위 혹은 아래로 이동하는 메서드는 위와같이 구현할 수 있지만, pageUp()과 pageDown()을 사용할 수도 있습니다.
webView.pageUp(true) // 페이지 상단으로 이동
webView.pageDown(true) // 페이지 하단으로 이동
이렇게 웹뷰를 사용하는 기본적인 방법에 대해 알아보았습니다. 이 밖에도 매우 여러가지의 기능들과 처리들이 존재하기 때문에, 웹의 구성방식과 앱과의 통신방식에 따라 사용되는 기능들을 찾아서 사용하시면 되겠습니다.
감사합니다.
2023-09-04 추가 : 웹페이지에서 캐시를 사용하는 방법에 대한 포스트가 업로드되었습니다.
2023.09.04 - [Android] - [안드로이드] 웹뷰(WebView)(3) - 브라우저 캐시 사용하기
참고
https://developer.android.com/develop/ui/views/layout/webapps/webview?hl=ko
https://developer.android.com/guide/topics/resources/runtime-changes?hl=ko
코드
https://github.com/tekken5953/WebViewExam
'Android' 카테고리의 다른 글
[안드로이드] WifiManager로 연결 가능한 와이파이 검색하기 (0) | 2023.01.30 |
---|---|
[안드로이드] savedInstanceState 는 왜 있는걸까? (0) | 2023.01.06 |
[안드로이드] 웹뷰(WebView)(1) - 앱 브라우저에서 호출 (0) | 2022.12.26 |
[안드로이드] 아래에서 올라오는 다이얼로그 - BottomSheetDialogFragment (0) | 2022.12.14 |
[안드로이드] Spannable로 글자마다 다른 설정! (0) | 2022.12.13 |