반응형

안드로이드에서 WebView를 사용하면 별도의 서버에서 호스팅 되고 있는 웹 컨텐츠를 보여줄 수도 있고, 별도의 웹 서버를 두지 않고 local static file(html, css, js)만을 사용하여 웹 페이지를 제공할 수도 있습니다.

 

그렇다면 WebView에서 local file에 대해서는 어떻게 접근할 수 있을까요? 한 가지 방법만 있는 것은 아닙니다만 오늘 소개드릴 방법은 assets 폴더에 넣고 접근하는 방법입니다.

 

Assets

Assets에 대해 간단하게 설명을 드리자면, 단어 뜻 그대로 "자산"입니다. 프로젝트가 패키징 할 때 함께 assets 디렉토리에 위치한 파일들을 포함하여 런타임에서 접근할 수 있게 합니다.

 

Assets은 res 디렉토리가 아닌 assets/ 이라는 디렉토리에서 관리되는데, 프로젝트 생성시 기본적으로 생성되는 디렉토리가 아니기 때문에 따로 생성해줘야 합니다.

 

Assets은 종종 res/raw 디렉토리와 비교되곤 합니다.

 

res/raw 와의 결정적인 차이는 res/raw 아래 존재하는 파일들은 R 클래스에 의해 id 값이 관리되기 때문에 컴파일 타임에서 파일 존재에 대한 검사가 발생하게 되고, 디렉토리를 다양하게 구성하여 관리할 수 없습니다.

 

반면에 Assets 방식은 R 클래스를 통해 리소스가 관리되지 않기 때문에 컴파일이 아닌 런타임에서 검사가 발생하기 때문에 좀 더 유연하게 파일에 대한 접근을 할 수 있습니다. 그리고 file path에 의한 접근이 가능하기 때문에 assets/ 디렉토리 하에 다양한 디렉토리를 두어 리소스 관리의 편의성을 높일 수 있습니다.

 

WebView with Assets

본론으로 돌아와서 웹뷰에서 local file에 접근하는 수단으로 Assets을 사용해보도록 하겠습니다.

 

먼저 html과 js 파일을 준비해보도록 하겠습니다.

 

sample.html

<!DOCTYPE html>
<html>
<head>
    <title>Ready Story</title>
</head>
<body>

    <h1 id="sample-title">Sample for the injected local js file.</h1>
    <script type="text/javascript" src="sample.js"></script>
</body>
</html>

 

sample.js

(function() {
    document.getElementById("sample-title").style.fontStyle = "italic";
}());

 

정말 간단한 파일입니다. 여기서 눈여겨 볼 것은 sample.html 내에서 sample.js를 호출할 때 상대 경로로 호출한다는 부분입니다. 그렇기 때문에 sample.html과 sample.js를 같은 경로에 둬야 합니다.

(꼭 그래야만 하는 것은 아닙니다. WebViewClient의 shouldInterceptRequest()을 이용하여 호출을 가로챈 다음 적절한 데이터를 주입해주는 방식도 있습니다만, 관련해서는 다른 포스팅에서 다루도록 하겠습니다.)

 

먼저 assets 폴더를 만들어줍니다.

주의해야 하는 것은 res/ 폴더 아래 만드는 것이 아니라 동등한 위치에 만들어줘야 한다는 것입니다.

 

 

그리고 assets/ 아래위에서 만든 파일들을 넣어줍니다.

 

다음으로 Activity 안에 WebView가 가득 차도록 layout을 정의합니다.

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <WebView
        android:id="@+id/web_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

마지막으로 Activity에서 WebView에 local file에 대한 url을 연결해줍니다.

WebView 내에서 JavaScript 파일을 사용하기 때문에 WebView#getSettings()#setJavaScriptEnabled() 를 설정해줍니다.

 

MainActivity.kt

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        web_view.settings.javaScriptEnabled = true
        web_view.loadUrl("file:///android_asset/sample.html")
    }
}

 

위 코드에서 보시다시피 assets/ 디렉토리에 대한 url은 "file:///android_asset/" 을 baseUrl로 두고서 접근하시면 됩니다.

 

결과 화면

결과 화면처럼 텍스트에 기울임꼴(Italic)이 잘 적용되었다면 정상적으로 적용된 것이구요. 만약에 기울임꼴이 적용되지 않았다면 js 파일이 제대로 로드되지 않은 것이니 파일 경로나 오타는 없는지 확인하시기 바랍니다.

 

전체 예제 코드는 Github 저장소에서 확인할 수 있습니다.

반응형
반응형