본문 바로가기
Android/WebView

[Android] Webview 정리

by 태크민 2023. 10. 6.

WebView

  • 웹 탐색과 웹 브라우저는 Android, iOS, PC 모두 가진 기능입니다.
  • WebView는 웹 브라우저를 구성하는 HTML과 같은 요소들을 받아들여 이를 브라우저와 동일한 형식으로 해석해서 표현해주는 뷰입니다.
  • 그래서 WebView는 PC의 서버에서 response 한 웹 파일을 받아서 Android에서도 똑같이 보여주고 다룰 수 있고, 디바이스 상관없이 정보 공유가 가능한 하이브리드 앱을 쉽게 구현할 수 있도록 도와줍니다.

 

URL 웹 페이지 요청

  • 단순히 WebView를 참조하고 loadUrl로 웹 브라우저를 실행하여 해당 url을 로드하는 방법입니다.
  • loadUrl 메소드를 사용해서 해당 주소에 요청을 보내고, 응답받은 html 파일을 사용하여 웹 화면을 표시합니다.
  • WebView에 WebViewClient를 제공함으로써 웹 페이지를 WebView에 띄울 수 있게 됩니다.
 binding.webView.apply {
            webViewClient = WebViewClient()
            loadUrl("https://www.google.com/")
        }

 

 

내부 html 요청

  • 개발자가 가진 html 파일을 표시하려면, 이 파일이 assets 폴더 안에 존재해야 합니다.
  • assets은 res폴더 처럼 리소스를 모아두는 곳인데, res에서 분류한 타입 외의 html, css, js 등을 사용할 때에 사용하는 폴더입니다.
  • 아래와 같이 assets 폴더 안에 html 파일을 넣고 loadUrl 메소드를 사용하여 불러옵니다.

 

webView.loadUrl("file:///android_asset/www/index.html")

 

 

html을 parsing하여 보여주기

  • 일반적으로 사용하는 loadUrl() 메소드로 html parsing 하여 필요한 부분만 보여줄 수 없습니다.
  • 이러한 경우 loadData 메소드나 loadDataWithBaseURL 메소드를 이용하면 됩니다.
  • loadData(String data, String mimeType, String encoding) ->
    html태그들을 String으로 가지고 있을 경우 loadData(data, mimeType, encoding) 함수를 통해 사용한다.
    data : encoding으로 작성된 data는 html 코드를 string 형태로 넣어서 사용할 수 있습니다.
    mimeType : 문서의 다양성을 알려주기 위함으로 "text/html" 등의 값을 가질 수 있습니다.
    encoding : data가 어떤 형태의 encoding으로 작성되었는지 알려줍니다.
  • 하지만, loadData 메소드는 network 상의 content를 WebView에 보여줄 수 없습니다. 즉 html 내용 중 상대 경로로 있는 스타일이나 이미지 등을 못 가져오는 경우가 있습니다.
  • 예를 들어 <link="stylesheet" href="/Content/Css/main.css?2016011909href="/Content/Css/main.css? 2016011909" /> 이런 css가 있다고 하면 /Content 폴더가 어디 경로를 기점인지 알 수가 없어 loadDataWithBaseUrl을 사용하여 해결합니다.
  • loadDataWithURL(String baseUrl, String data, String mimeType, String encoding, String histroyUrl) -> baseUrl : 상대 경로를 해결하기 위해 사용됨. historyUrl : histroy entry로 사용됨.
String data ="<h5>가나다라마</h5>";
loadData(data, "text/html; charset=utf-8", "UTF-8")
loadDataWithBaseURL(url, data, "text/html; charset=utf-8", "UTF-8", null)

 

java script 연동 (앱 -> 웹뷰 JavaScript 호출)

  • 웹 브라우저는 java script를 사용합니다.
  • 단순히 받아온 코드를 해석하는 것은 문제가 없을지 몰라도, 화면에 표시되는 웹 페이지와 안드로이드 코드가 유기적으로 동작하기 어려울 수 있습니다.
  • 하지만, 이를 지원해주는 api가 존재합니다.
  • loadUrl 메소드에 java script의 함수명을 적어주어, 정의된 함수를 실행시킬 수 있습니다.
  • 앱의 동작에 연동하여 java script의 어떠한 동작을 하도록 이벤트를 걸 때 사용하면 좋습니다.
webView.loadUrl("javascript:alerthello()")

 

 

WebView와 앱 통신  (웹뷰 -> 앱 코드 호출)

  • WebView는 보안상의 이유로 디바이스 자원을 100% 사용할 수 없습니다. 보통 안드로이드는 디바이스 유일 값으로 Android Id를 사용하는데 디바이스 영역으로 웹뷰에서 바로 접근하여 추출할 수 없습니다.
  • 하지만, 네이티브에서는 해당 값을 자유롭게 추출 가능합니다. 이와 같은 경우 웹뷰와 네이티브의 연동을 통해 값을 전달합니다.
  • 본 연동방식은 안드로이드 OS 4.1 JELLY_BEAN 이하 디바이스에서는 보안상 문제가 있어, 안드로이드 OS 4.2 이상에서 사용을 권장하고 있습니다. 안드로이드 OS 4.1 이하에서는 @JavaScriptinterface 어노테이션이 동작하지 않습니다.
JavaScript에서 네이티브 메소드 호출
  • JavaScript에서 네이티브 코드 호출 -> 네이티브 코드가 JavaScriptInterface 어노테이션이 지정되었는지 확인하고 지정되어 있으면 네이티브 메소드를 실행 -> 네이티브 메소드의 실행결과를 반환.
네이티브에서 JavaScript 호출

 

  • evaluteJavascript를 통해 JavaScript 호출 -> 실행결과를 반환.

 

 

웹뷰에서 앱 코드를 호출하는 예제를 보겠습니다.

  • assets 폴더에 html 파일을 만들어줍니다. 안드로이드에서 선언한 함수를 호출할 수 있습니다.
<input type="button" value="WebView Test" onClick="showAndroidToast('Connection Success!')"/>
<script type="text/javascript">
    function showAndroidToast(toast) {
        Android.showToast(toast);
    }

</script>
  • @JavascriptInterface 함수 생성.
webview.settings.javaScriptEnabled = true
webview.addJavascriptInterface(WebAppInterface(this), "Android")
webview.loadUrl("file:///android_asset/www/index.html")

/** Instantiate the interface and set the context  */
class WebAppInterface(private val mContext: Context) {
	/** Show a toast from the web page  */
    @JavascriptInterface
    fun showToast(toast: String) =
        Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show()
}

 

 

WebView Settings

binding.webView.settings.apply {
            setSupportMultipleWindows(false) // 새창 띄우기 허용 
            setSupportZoom(false) // 화면 확대 허용 
            javaScriptEnabled = true // 자바스크립트 허용 
            javaScriptCanOpenWindowsAutomatically = false // 자바스크립트 새창 띄우기 허용 
            loadWithOverviewMode = true // html의 컨텐츠가 웹뷰보다 클 경우 스크린 크기에 맞게 조정 
            useWideViewPort = true // html의 viewport 메타 태그 지원 
            builtInZoomControls = false // 기본적으로 줌 기능이 되지 않습니다.
            displayZoomControls = false // 화면 확대/축소 허용 
            layoutAlgorithm = WebSettings.LayoutAlgorithm.SINGLE_COLUMN // 컨텐츠 사이즈 맞추기 
            cacheMode = WebSettings.LOAD_NO_CACHE // 브라우저 캐쉬 허용 
            domStorageEnabled = true // 로컬 저장 허용 
            databaseEnabled = true
            /**
             * * This request has been blocked; the content must be served over HTTPS
             * * https 에서 이미지가 표시 안되는 오류를 해결하기 위한 처리
             * */
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
            }
        }
 binding.webView.apply {
  		webViewClient = WebViewClient()     // WebView 위젯을 사용해 여러 기능 사용
        webChromeClient = WebChromeClient() // 브라우저 크롬에 특화
       }

 


WebViewClinet와 WebChromeClient

웹뷰를 구현하기 할때 WebView객체를 만들게 되는데요, 단순히 WebView객체만 생성하면 화면만 보여질 뿐 웹뷰 속 버튼이나 다른 기능들은 동작하지 못합니다. 웹뷰 속 버튼을 앱에서 제어하기 위해 필요한 구현체들이 바로 WebViewClient WebChromeClient입니다.

 

먼저 WebViewClient와 WebChromeClient 이 둘의 차이를 알아봅시다.

WebViewClient웹페이지를 로딩할때 생기는 콜백함수들로 구성되어 있습니다. 

반면 WebChromeClient웹페이지에서 일어나는 액션들에 관한 콜백함수들로 구성되어 있습니다. 예를들면 웹에서 새 창을 띄우려하거나 파일을 첨부하는 경우가 있습니다. 

 

아래는 각 클래스에서 자주 오버라이드 하는 함수들 입니다. 

WebViewClient 함수

함수명 반환 호출 시점 설명
onPageStarted void 페이지가 로딩되는 첫 시점에 한번 호출된다.  
shouldOverridingUrlLoading boolean 웹뷰에서 url이 로딩될때 호출되어 앱에게 제어할 기회를 준다. 앱이 url로딩을 제어할 경우 true를 반환, 그게 아니면 default로 false를 반환한다.
onPageFinished void 페이지 로딩이 끝나면 호출된다.  

WebChromeClient 함수

함수명 반환 호출 시점 설명
onProgressChanged void 페이지가 로딩되는 중간중간 호출된다.  현재 로딩되는 페이지의 상태를 알려준다. 
onCreateWindow boolean 웹에서 새 창을 열때 호출된다. 앱이 새 창을 여는 작업을 하면 true를 반환, 그게 아니면 default로 false를 반환한다.
onCloseWindow void 웹뷰가 창을 닫을 때 호출된다.  

 

자주쓰이는 함수들

경우에 따라 자주쓰이는 함수들입니다. 

경우 1) 웹에서 사용자 이벤트로 새로운 url이 로딩된다 → shouldOverrideUrlLoading()

경우 2) 웹에서 window.open으로 새탭이 열린다 → onCreateWindow()

호출 flow

위에 설명한 내용을 토대로 웹뷰의 전체적인 호출 순서를 도식화 했습니다.

모든 함수를 넣진 못했지만, 가장 많이 쓰이는 함수들로 넣었습니다.

 


출처

https://yoon-dailylife.tistory.com/109

 

Android) WebView 정리

WebView 웹 탐색과 웹 브라우저는 Android, iOS, PC 모두 가진 기능입니다. WebView는 웹 브라우저를 구성하는 HTML과 같은 요소들을 받아들여 이를 브라우저와 동일한 형식으로 해석해서 표현해주는 뷰입

yoon-dailylife.tistory.com

https://kyome.tistory.com/149

 

[Android] WebView 설정 모아보기

웹뷰 설정은 매번 기억이 안나기 때문에 기록해두는게 마음편하다. WebView webView = findViewById(R.id.webView); webView.getSettings().setJavaScriptEnabled(true); // 자바스크립트 사용여부 webView.getSettings().setJavaScript

kyome.tistory.com

https://kimdabang.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-WebViewClient%EC%99%80-WebChromeClient

 

[안드로이드] WebViewClient와 WebChromeClient

웹뷰를 구현하기 할때 WebView객체를 만들게 되는데요, 단순히 WebView객체만 생성하면 화면만 보여질 뿐 웹뷰 속 버튼이나 다른 기능들은 동작하지 못합니다. 웹뷰 속 버튼을 앱에서 제어하기 위해

kimdabang.tistory.com