WebView - создай свой браузер

Загружаем локальные страницы и картинки
Загружаем данные при помощи loadData() и loadDataWithBaseURL()
Проблемы с кодировкой
Используем зум для просмотра

Элемент WebView позволяет создать собственное окно для просмотра веб-страниц или даже создать свой клон браузера. Сам элемент использует движок WebKit и имеет множество свойств и методов. Мы ограничемся базовым примером создания приложения, с помощью которого сможем просматривать страницы в интернете.

Создадим новый проект HelloWebView и сразу заменим код в файле res/layout/main.xml:


<?xml version="1.0" encoding="utf-8"?>
<WebView  xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/webview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
/>

Теперь откроем файл HelloWebView.java и объявим объект WebView, а также инициализируем его: включаем поддержку JavaScript и указываем страницу для загрузки


WebView mWebView;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
            
    mWebView = (WebView) findViewById(R.id.webview);
    mWebView.getSettings().setJavaScriptEnabled(true); // включаем поддержку JavaScript
    mWebView.loadUrl("http://developer.alexanderklimov.ru"); // указываем страницу загрузки
	...

Так как приложение будет использовать интернет, необходимо установить разрешение на доступ к интернету в файле-манифесте.


<uses-permission android:name="android.permission.INTERNET" />

Также модифицируем строчку для экрана, удалив заголовок из нашего приложения (выделено жирным):


<activity android:name=".HelloWebViewActivity"
    android:label="@string/app_name"
    android:theme="@android:style/Theme.NoTitleBar">

Запустим приложение. В нашем распоряжении появился простейший вьювер веб-страниц. Но с одним недостатком. Если вы щелкнете на любой ссылке, то у вас автоматически запустится браузер по умолчанию и новая страница отобразится уже там. Поначалу я даже не понял, что уже нахожусь не в своей программе, а в браузере.

Страница в браузере

Но опытный пользователь сразу увидит, что появился заголовок браузера, кнопка для закладки и т.д. Чтобы решить данную проблему и открывать ссылки в своей программе, нужно переопределить класс WebViewClient и позволить нашей странице приложения обрабатывать ссылки. Добавим в коде вложенный класс:


private class HelloWebViewClient extends WebViewClient 
{
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) 
    {
        view.loadUrl(url);
        return true;
    }
}

Также после метода onCreate(Bundle) установим экземпляр HelloWebViewClient как WebViewClient. Она может находиться в любом месте после инициализации объекта WebView:


mWebView.setWebViewClient(new HelloWebViewClient());

Теперь в нашем приложении создан WebViewClient, который позволяет загружать любой указанный URL, выбранный в WebView, снова в сам контейнер WebView, а не запускать бразуер. За данную функциональность отвечает метод shouldOverrideUrlLoading(WebView, String), в котором мы указываем текущий WebView и нужный URL. Возвращаемое значение true говорит о том, что мы не нуждаемся в запуске стороннего браузера, а самостоятельно загрузим контент по ссылке.

Повторно запустите приложение, и убедитесь, что ссылки загружаются теперь в самом приложении. Но теперь возникла еще одна проблема. Мы не можем вернуться к предыдущей странице. Если мы нажмем на кнопку BACK (Назад) на своем устройстве, то просто закроем свое приложение. Для решения новой проблемы нам необходимо обрабатывать нажатие кнопки BACK. Добавляем новый метод на странице HelloWebView:

 
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) 
{
    if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) 
	{
        mWebView.goBack();
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

Метод обратного вызова onKeyDown(int, KeyEvent) вызывается при нажатии любой кнопки в приложении. Мы должны проверить, что нажатая кнопка является кнопкой BACK (KeyEvent.KEYCODE_BACK), а также убедиться, что WebView поддерживает навигацию на предыдущую страницу (включено по умолчанию), если она существует. Если оба условия верны, тогда вызывается метод goBack(), который возвращает нас на предыдущую страницу на одиш шаг. Если таких страниц набралось несколько, то мы можем последовательно вернуться к самой первой странице. При этом метод всегда будет возвращать значение true. Когда мы вернемся на самую первую страницу, с которой начали путешествие по интернету, то вернется false и обработкой нажатия кнопки BACK займется уже сама система, которая закроет страницу приложения.

Запустите приложение еще раз. Теперь у вас появился свой собственный веб-браузер, позволяющий ходить по ссылкам и возвращаться на предыдущую страницу. Изучив документацию, вы можете оснастить приложение и другим вкусными плюшками для своего браузера.

WebView

Загружаем локальные страницы и картинки

Если вы хотите загружать в WebView страницы не из интернета, а со своего приложения, то разместите нужные файлы в папке /res/assets, например, res/assets/mypage.html. Доступ к файл вы можете получить через конструкцию file://android_asset:


myBrowser = (WebView)findViewById(R.id.mybrowser);
      
myBrowser.loadUrl("file:///android_asset/mypage.html");

Аналогично поступаем с картинками


<img src="file:///android_asset/myimage.gif">

Загружаем данные при помощи loadData() и loadDataWithBaseURL()

Данные можно загрузить с помощью метода loadData():


String htmlText = "<html><body>Percent test: 100% </body></html>";
WebView mWebView = (WebView) findViewById(R.id.webView);
mWebView.loadData(htmlText, "text/html", "en_US");

Если текст простой, то этот способ подойдет. Но в данном примере встречается символ процента, который относится к спецсимволам и часть текста может оказаться недоступной. Если в тексте встречаются подобные символы, то лучше использовать метод loadDataWithBaseURL():


mWebView.loadDataWithBaseURL(null, htmlText, "text/html", "en_US", null);

Проблемы с кодировкой

У меня есть программа, использующая WebView, которая доступна в Google Play. К моему удивлению, некоторые пользователи жаловались, что текст нечитаем, так как они видят только кракозябры. Особенно много жалоб было от пользователей с планшетами. Оказалось, что проблема довольна распространенная и обсуждается на форумах. Танцы с бубнами (установка явной кодировки UTF-8) не помогают. Нашёл один ответ, который считается рабочим, на всякий случай я его здесь оставлю. Сам не проверял и работоспособность не гарантирую.


// перед загрузкой данных (load...)
WebSettings settings = mWebView.getSettings();
settings.setDefaultTextEncodingName("utf-8");

Используем зум для просмотра

Не забывайте, что WebView можно использовать не только для просмотра html-страниц, но и для просмотра изображений. Поэтому данный элемент вполне можно использовать как вьювер картинок, к тому же вы можете включить встроенный механизм зумирования:


mWebView = (WebView) findViewById(R.id.webView1);
// устанавливаем Zoom control
mWebView.getSettings().setBuiltInZoomControls(true);
		
// загружаем картинку (не забудьте установить разрешение на интернет)
mWebView.loadUrl("http://netsources.narod.ru/friday/alkocat.jpg");
this.setTitle("WebView");
Zoom