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 메소드를 사용하여 불러옵니다.
![](https://blog.kakaocdn.net/dn/NiYUe/btq85lVV0BM/2oGxYEKMf7WYZZGcVw9o71/img.png)
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 어노테이션이 동작하지 않습니다.
![](https://blog.kakaocdn.net/dn/cf4RYK/btq86gf4j8m/VJkAin1TNUTgRK1Q2X8se0/img.png)
- JavaScript에서 네이티브 코드 호출 -> 네이티브 코드가 JavaScriptInterface 어노테이션이 지정되었는지 확인하고 지정되어 있으면 네이티브 메소드를 실행 -> 네이티브 메소드의 실행결과를 반환.
![](https://blog.kakaocdn.net/dn/doTBut/btq83i7vV4t/NYkHogGNgRZnlCM31zuEb0/img.png)
- 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
[Android] WebView 설정 모아보기
웹뷰 설정은 매번 기억이 안나기 때문에 기록해두는게 마음편하다. WebView webView = findViewById(R.id.webView); webView.getSettings().setJavaScriptEnabled(true); // 자바스크립트 사용여부 webView.getSettings().setJavaScript
kyome.tistory.com
[안드로이드] WebViewClient와 WebChromeClient
웹뷰를 구현하기 할때 WebView객체를 만들게 되는데요, 단순히 WebView객체만 생성하면 화면만 보여질 뿐 웹뷰 속 버튼이나 다른 기능들은 동작하지 못합니다. 웹뷰 속 버튼을 앱에서 제어하기 위해
kimdabang.tistory.com