게시일: 2014년 2월 28일
새 Android 프로젝트를 만들고, WebView를 추가하고, 원격 URL을 로드하고, 로컬 HTML 페이지를 로드하는 방법을 알아봅니다.
이 튜토리얼에서는 Android 개발 환경에 대한 경험이 제한적이거나 전혀 없지만 Kotlin에 대한 경험이 있는 개발자를 대상으로 합니다. 이미 Android 프로그래밍에 익숙한 경우 Android 개발자 사이트에서 WebView에서 웹 앱 빌드를 읽어보세요.
Android 스튜디오 설치
이 튜토리얼에서는 Android용 설계 및 빌드 IDE인 Android 스튜디오를 사용합니다.
새 Android 프로젝트 만들기
Android 스튜디오가 설치되면 설정 마법사가 실행됩니다.
새 프로젝트를 만들려면 다음과 같이 합니다.
- 새 프로젝트를 클릭합니다.
- Empty Activity 템플릿을 클릭하여 프로젝트에 선택합니다. 템플릿은 프로젝트의 구조와 Android 스튜디오에서 프로젝트를 빌드하는 데 필요한 파일을 만듭니다.
- 다음을 클릭하여 새 프로젝트 대화상자를 엽니다.
- 프로젝트를 구성합니다. 애플리케이션 이름, 패키지 이름, 타겟 SDK를 입력합니다. 그런 다음 Next를 클릭합니다.
- 최소 필수 SDK를 API 24: Android 7.0 (Nougat)으로 설정합니다.
- 마침을 클릭합니다.
Android 스튜디오에서 새 프로젝트가 열립니다.
프로젝트 구조
Android 스튜디오에서 만든 초기 프로젝트에는 애플리케이션을 설정하는 템플릿 코드가 있습니다. 몇 가지 더 중요한 폴더는 다음과 같습니다.
src/main/java
. Android Java 소스 코드src/main/res
. 애플리케이션에서 사용하는 리소스입니다.src/main/res/drawable
: 애플리케이션에서 사용하는 이미지 리소스입니다.src/main/res/xml
. UI 구성요소의 구조를 정의하는 XML 레이아웃 파일입니다.src/main/res/values
. 애플리케이션에 하드코딩하고 싶지 않은 크기, 문자열, 기타 값입니다.src/main/AndroidManifest.xml
. 매니페스트 파일은 활동, 권한, 테마와 같이 애플리케이션에 포함된 항목을 정의합니다.
WebView 추가
그런 다음 기본 활동의 레이아웃에 WebView를 추가합니다.
src/main/res/xml
디렉터리의activity_main.xml
파일이 아직 열려 있지 않으면 엽니다.fragment_main.xml
파일도 표시될 수 있습니다. 이 튜토리얼에서는 필요하지 않으므로 무시해도 됩니다.activity_main.xml
편집기 하단에서 Text 탭을 선택하여 XML 마크업을 확인합니다.이 파일은 기본 활동의 레이아웃을 정의하며 미리보기 창에는 활동의 미리보기가 표시됩니다. 빈 활동 레이아웃에는 하위 요소가 포함되지 않습니다. WebView를 추가해야 합니다.
XML 창에서
FrameLayout
요소의 끝에서 자체 닫기 슬래시를 삭제하고 다음과 같이<WebView>
요소와 새 닫기 태그를 추가합니다.<FrameLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:tools="https://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> tools:ignore="MergeRootFrame"> <WebView android:id="@+id/activity_main_webview" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout>
WebView를 사용하려면 Activity에서 참조해야 합니다.
src/main/java/<PackageName>
디렉터리에서 기본 활동의 Java 소스 파일인MainActivity.java
를 엽니다.굵게 표시된 줄을 추가합니다.
public class MainActivity extends Activity { private WebView mWebView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mWebView = (WebView) findViewById(R.id.activity_main_webview);
onCreate
메서드의 기존 코드는 Activity를 레이아웃에 연결하는 작업을 실행합니다. 추가된 줄은 웹 뷰를 참조하는 새 멤버 변수mWebView
를 만듭니다.다음 코드를 삭제합니다.
if (savedInstanceState == null) { getSupportFragmentManager().beginTransaction() .add(R.id.container, new PlaceholderFragment()) .commit(); }
WebView는 레이아웃 파일의 이 줄에 지정된 리소스 ID로 식별됩니다.
android:id="@+id/activity_main_webview"
코드를 추가하면 편집기의 여백에 경고 메시지가 표시됩니다. WebView에 적절한 클래스를 가져오지 않았기 때문입니다. 다행히 Android 스튜디오를 사용하면 누락된 클래스를 채울 수 있습니다. 가장 쉬운 방법은 알 수 없는 클래스 이름을 클릭하고 마우스를 가져간 다음 '빠른 수정'을 보여주는 모듈이 표시될 때까지 기다리는 것입니다. 이 경우
WebView
클래스에import
문을 추가합니다.Alt + Enter (Mac의 경우 Option + Enter)를 눌러 빠른 수정을 수락합니다.
WebView를 준비했으면 이제 WebView를 설정하고 흥미로운 웹 콘텐츠를 로드해 보겠습니다.
자바스크립트 사용
WebView는 기본적으로 JavaScript를 허용하지 않습니다. WebView에서 웹 애플리케이션을 실행하려면 onCreate
메서드에 다음 줄을 추가하여 JavaScript를 명시적으로 사용 설정해야 합니다.
// Enable Javascript
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
원격 URL 로드
원격 URL에서 데이터를 로드하려면 애플리케이션에 인터넷에 액세스할 수 있는 권한이 필요합니다. 이 권한은 애플리케이션의 매니페스트 파일에 추가해야 합니다.
src/res
디렉터리에서AndroidManifest.xml
파일을 엽니다. 닫는</manifest>
태그 앞에 굵은 줄을 추가합니다.<?xml version="1.0" encoding="utf-8"?> <manifest ...> ... </application> <uses-permission android:name="android.permission.INTERNET" /> </manifest>
다음 단계는 WebView에서
loadUrl
메서드를 호출하는 것입니다.onCreate
메서드 끝에 다음 줄을 추가합니다.mWebView.loadUrl("[https://beta.html5test.com/][8]");
이제 프로젝트를 실행해 봅니다. 기기가 없다면 Tools > Android > AVD Manager로 이동하여 에뮬레이터 (AVD 또는 Android Virtual Device)를 만들 수 있습니다.
탐색 처리
로드하는 URL을 https://www.css-tricks.com/
로 변경하고 애플리케이션을 다시 실행해 보세요. 이상한 점이 눈에 띌 것입니다.
이제 css-tricks.com
와 같은 리디렉션이 있는 사이트를 사용하여 애플리케이션을 실행하면 앱이 WebView가 아닌 기기의 브라우저에서 사이트를 열게 됩니다. 이는 예상한 결과가 아닙니다. 이는 WebView에서 탐색 이벤트를 처리하는 방식 때문입니다.
다음은 이벤트 순서입니다.
- WebView가 원격 서버에서 원래 URL을 로드하려고 시도하고 새 URL로 리디렉션됩니다.
- WebView는 시스템이 URL의 뷰 인텐트를 처리할 수 있는지 확인합니다. 시스템이 처리할 수 있는 경우 시스템이 URL 탐색을 처리하고, 그렇지 않으면 WebView가 내부적으로 탐색합니다 (예: 사용자의 기기에 브라우저가 설치되어 있지 않은 경우).
- 시스템은
https://
URL 스키마를 처리하기 위해 사용자가 선호하는 애플리케이션(즉, 사용자의 기본 브라우저)을 선택합니다. 브라우저가 두 개 이상 설치된 경우 이 시점에 대화상자가 표시될 수 있습니다.
Android 애플리케이션 내에서 WebView를 사용하여 콘텐츠 (예: 도움말 페이지)를 표시하는 경우 이 방법이 가장 적합할 수 있습니다. 하지만 더 정교한 애플리케이션의 경우 탐색 링크를 직접 처리하는 것이 좋습니다.
WebView 내에서 탐색을 처리하려면 WebView에서 생성된 다양한 이벤트를 처리하는 WebView의 WebViewClient
를 재정의해야 합니다. 이를 사용하여 WebView가 링크 클릭 및 페이지 리디렉션을 처리하는 방식을 제어할 수 있습니다.
WebViewClient
의 기본 구현은 WebView에서 모든 URL을 엽니다.
// Force links and redirects to open in the WebView instead of in a browser
mWebView.setWebViewClient(new WebViewClient());
이는 좋은 출발이지만 브라우저에서 다른 URL을 열면서 사이트의 링크만 처리하려면 어떻게 해야 하나요?
이렇게 하려면 WebViewClient
클래스를 확장하고 shouldOverrideUrlLoading
메서드를 구현해야 합니다. 이 메서드는 WebView가 다른 URL로 이동하려고 할 때마다 호출됩니다. false를 반환하면 WebView에서 URL 자체를 엽니다. 기본 구현은 항상 false를 반환하므로 이전 예에서 작동합니다.
새 클래스를 만듭니다.
- 앱의 패키지 이름을 마우스 오른쪽 버튼으로 클릭하고 새로 만들기 > Java 클래스를 선택합니다.
- 클래스 이름으로
MyAppWebViewClient
를 입력하고 OK를 클릭합니다. 새
MyAppWebViewClient.java
파일에 다음 코드를 추가합니다 (변경사항은 굵게 표시됨).public class MyAppWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if(Uri.parse(url).getHost().endsWith("css-tricks.com")) { return false; } Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); view.getContext().startActivity(intent); return true; } }
새 코드는
MyAppWebViewClient
를WebViewClient
의 서브클래스로 정의하고shouldOverrideUrlLoading
메서드를 구현합니다.shouldOverrideUrlLoading
메서드는 WebView가 URL을 로드하려고 할 때마다 호출됩니다. 이 구현은 URL의 호스트 이름 끝에 있는 문자열 'css-tricks.com'을 확인합니다. 문자열이 있으면 메서드는 false를 반환하여 플랫폼에 URL을 재정의하지 않고 WebView에 로드하도록 지시합니다.다른 호스트 이름의 경우 메서드는 시스템에 URL을 열도록 요청합니다. 새 Android 인텐트를 만들고 이를 사용하여 새 활동을 시작합니다. 메서드 끝에서 true를 반환하면 URL이 WebView에 로드되지 않습니다.
새 맞춤 WebViewClient를 사용하려면
MainActivity
클래스에 다음 줄을 추가합니다.// Stop local links and redirects from opening in browser instead of WebView mWebView.setWebViewClient(new MyAppWebViewClient());
이제 사용자는 CSS Tricks 링크를 클릭하고 앱 내에서 계속 머물 수 있지만 외부 사이트 링크는 브라우저에서 열립니다.
Android 뒤로 버튼 처리
CSS Tricks 도움말을 둘러보고 탐색하기 시작하면 Android에서 뒤로 버튼을 클릭하면 애플리케이션이 종료됩니다.
WebView 메서드 canGoBack
는 페이지 스택에 팝할 수 있는 항목이 있는지 알려줍니다. 뒤로 버튼 누르기를 감지하고 WebView의 기록을 통해 뒤로 이동해야 하는지 또는 플랫폼에서 올바른 동작을 결정하도록 허용해야 하는지 결정하려면 MainActivity
에 onBackPressed()
메서드를 추가합니다.
public class MainActivity extends Activity {
private WebView mWebView;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
}
@Override
public void onBackPressed() {
if(mWebView.canGoBack()) {
mWebView.goBack();
} else {
super.onBackPressed();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
...
}
}
파일 시스템에서 HTML 로드
설치 가능한 애플리케이션 내에서 WebView를 사용하는 큰 이점 중 하나는 앱 내에 애셋을 저장할 수 있다는 것입니다. 이렇게 하면 WebView가 로컬 파일 시스템에서 애셋을 직접 가져올 수 있으므로 앱이 오프라인으로 작동하고 로드 시간이 개선됩니다.
HTML, JavaScript, CSS를 비롯한 파일을 로컬에 저장하려면 애셋 디렉터리에 저장합니다. Android에서 원시 파일에 사용하는 예약된 디렉터리입니다. 앱이 특정 파일을 최소화하거나 압축해야 할 수 있으므로 이 디렉터리에 액세스해야 합니다.
기본 (
src/main/assets/www
)에assets/www
디렉터리를 만듭니다.- 웹 파일은
/assets
의 하위 디렉터리에 두는 것이 좋습니다.
- 웹 파일은
모든 파일을 디렉터리에 업로드합니다.
적절한 파일을 로드합니다.
mWebView.loadUrl("file:///android_asset/www/index.html");
로컬이 아닌 페이지의 브라우저를 열도록
shouldOverrideUrlLoading
메서드를 업데이트합니다.public class MyAppWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if(Uri.parse(url).getHost().length() == 0) { return false; } Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); view.getContext().startActivity(intent); return true; } }
이제 멋진 WebView 앱을 빌드할 준비가 되었습니다.
시각적 요소를 적절하게 표시하는 방법에 관한 도움말은 WebView의 Pixel-Perfect UI를 참고하세요.
문제가 발생하면 Chrome DevTools를 사용하세요. 시작하려면 Android에서의 원격 디버깅을 참고하세요.