В Android есть несколько способов отображения HTML-страниц в вашем приложении. Наиболее эффективным способом является использование виджета Android WebView — о нем мы сегодня и поговорим.
Компонент WebView
в Android представляет собой полноценный браузер, который реализован как подкласс View,
поэтому мы с легкостью можем встроить его в наше приложение на Android.
Подробно о WebView в Android: что, как и почему
Чаще всего для работы с простыми html-страницами используется виджет TextView
. В этом случае мы можем реализовать статический метод fromHtml()
, который принадлежит утилитному HTML классу для парсинга строк с html кодом и дальнейшим его отображением в TextView
.
Виджет TextView
обеспечивает простое форматирование для стилей (жирный, курсив), шрифтов, различным цветов, гиперссылок и т.д.
Однако со сложным форматированием и большим объемом HTML-страниц виджет TextView
справиться уже не в состоянии. Например, работать с такими функциональными и объемными сайтами, как Facebook или другие соц сети через TextView
уже не получится.
В таких случаях на помощь приходит WebView
, так как только он может обрабатывать большие обхемы и множество HTML-тегов. Виждет WebView
также может работать с CSS
и JavaScript
, которые метод Html.fromHtml()
бы просто проигнорировал.
WebView
также обеспечивает работу с историей посещений и навигацией назад и вперед по страницам.
Тем не менее WebView
также имеет целый набор недостатков: с точки зрения эффективности потребления памяти он значительно уступает TextView
. Причиной большого потребления памяти WebView
является веб-движок рендеринга контента WebKit/Blink, который еще используется в таких браузерах, как Chrome.
Руководство по работе с WebView
Ниже представлен пример работы с макетом, установкой виджета в коде и обзор наиболее полезных методов при работе с WebView
в Android.
1. Установка WebView в макете
Компонент WebView
вставляется в тот файл XML-макета, где мы хотим видеть виджет WebView
. Давайте создадим простой Hello World проект на Android и посмотрим его работу в макете activity_main.xml
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="ua.com.prologistic.hellowebviewapp.MainActivity"> <WebView android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" /> </RelativeLayout> |
2. Инициализируем Android WebView в коде
Компонент WebView инициализируется в классе MainActivity
, с помощью идентификатора, ранее определенного в activity_main.xml
:
1 |
WebView webView = (WebView) findViewById (R.id.webView); |
3. Используем метод loadUrl()
После того, как мы получили ссылку на WebView, мы можем загрузить какой-то сайт с помощью протокола HTTP. Метод WebView
loadUrl()
используется для загрузки каких-либо URL в компонент WebView
, например:
1 |
webView.loadUrl("https://javadevblog.com"); |
Прежде чем мы начнем изучать WebView
дальше, есть два важных момента, которые нельзя упустить из вида:
- Поддержка JavaScript: JavaScript по умолчанию выключен в
Webview
. Следовательно, веб-страницы, содержащие JavaScript не будут работать должным образом. Чтобы его включить, используйте следующих фрагмент кода:
1 |
getSettings().setJavaScriptEnabled(true); |
- Добавление разрешений: чтобы загрузить ссылку в
WebView
, нам нужно добавить разрешение на доступ в Интернет вAndroidManifest.xml
нашего приложения:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ua.com.prologistic.hellowebviewapp"> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> |
Ниже представлен код класса MainActivity
со всеми указанными выше замечаниями:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
package ua.com.prologistic.hellowebviewapp; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.webkit.WebSettings; import android.webkit.WebView; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); WebView webView = (WebView) findViewById(R.id.webView); WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); webView.loadUrl("https://javadevblog.com"); } } |
Установка WebViewClient
Установка WebViewClient
нужна для того, чтобы пользователь нажимал на ссылку внутри веб-страницы нашего приложения и эта ссылка открывалась в нашем приложении, а не браузером по умолчанию.
Чтобы сохранить навигацию по ссылкам в нашем приложении с WebView
, мы должны создать подкласс WebViewClient
и переопределить метод shouldOverrideUrlLoading (WebView webView, String url)
. Давайте рассмотрим простой пример подкласса WebViewClient
:
1 2 3 4 5 6 |
private class SimpleWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView webView, String url) { return false; } } |
Здесь мы видим, что метод shouldOverrideUrlLoading()
возвращает false
. Это означает, что по нажатию на ссылку откроется вкладка внутри нашего приложения, а не стандартного браузера.
А теперь давайте изменим наше приложение так, чтобы оно открывало только ссылки сайта https://javadevblog.com, а по нажатию на ссылки других сайтов — спрашивало каким браузером воспользоваться.
Для этого в методе shouldOverrideUrlLoading()
нужно добавить всего лишь одно условие:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package ua.com.prologistic.hellowebviewapp; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.webkit.WebView; import android.webkit.WebViewClient; public class SimpleWebViewClientImpl extends WebViewClient { private Activity activity = null; public SimpleWebViewClientImpl(Activity activity) { this.activity = activity; } @Override public boolean shouldOverrideUrlLoading(WebView webView, String url) { // все ссылки, в которых содержится 'javadevblog.com' // будут открываться внутри приложения if (url.contains("javadevblog.com")) { return false; } // все остальные ссылки будут спрашивать какой браузер открывать Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); activity.startActivity(intent); return true; } } |
Навигация внутри Android WebView: нажатие кнопок вперед и назад
Если в разрабатываемом нами приложении нажать кнопку назад, то мы увидим, что приложение возвращается в главный экран, даже если мы осуществлять навигацию через несколько страниц внутри самого WebView
. Чтобы использовать историю просмотра ссылок внутри WebView
при нажатии кнопки назад, мы должны изменить переопределить функцию этой кнопки:
1 2 3 4 5 6 7 8 |
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK) && this.webView.canGoBack()) { this.webView.goBack(); return true; } return super.onKeyDown(keyCode, event); } |
Мы переопределили метод onKeyDown()
и теперь он сначала проверяет, что WebView
может вернуться на предыдущую ссылку, потому что WebView
поддерживает историю просмотра как обычный браузер. Если в истории ссылок нет, то нажатие на кнопку назад будет работать по умолчанию, то есть выходить из приложения.
Ниже весь код MainActivity
с указанными выше функциями:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
package ua.com.prologistic.hellowebviewapp; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.KeyEvent; import android.webkit.WebSettings; import android.webkit.WebView; public class MainActivity extends AppCompatActivity { private WebView webView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView = (WebView) findViewById(R.id.webView); WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); SimpleWebViewClientImpl webViewClient = new SimpleWebViewClientImpl(this); webView.setWebViewClient(webViewClient); webView.loadUrl("https://javadevblog.com"); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK) && this.webView.canGoBack()) { this.webView.goBack(); return true; } return super.onKeyDown(keyCode, event); } } |
Теперь запустите ваше приложение и переходите по ссылкам внутри сайта. Вы увидите, что все переходы происходят внутри приложения:
А все нажатия на ссылки, которые ведут на другие сайты спрашивают каким приложением открыть ссылку:
Загрузка контента в WebView: источники и способы
Кроме перехода по ссылкам в WebView
есть еще несколько способов загрузить контент, который предоставляется по средствам вызова метода loadUrl()
:
- Метод работает с указанием префикса к ссылке
http://
иhttps://
- А также:
file://путьКфайлу
— открывает локальный файл file:///android_asset/
— открывает файл, который находится в папкеassets
вашего приложенияcontent://
— работает сContentProvider
для получения контента.
Также есть метод loadData(), который принимает в параметры строку с html-кодом, например:
1 2 3 |
// здесь мы указываем, что это html-код с кодировкой utf-8 webView.loadData("<html><body>Hello, Android</body></html>", "text/html", "UTF-8"); |
Компонент WebView располагает большим количество методов для работы со ссылками, историей и другими элементами, однако мы рассмотрели наиболее используемые и полезные методы. Также мы написали небольшое приложение, которое открывает внутри себя только ссылки сайта https://javadevblog.com и спрашивает чем открыть ссылки на другие сайты.
Если статья была Вам полезна, подписывайтесь на новые статьи по Android и Java — впереди Вас ждет много интересных и полезных статей по современной разработке!
а можно полностью обьядиняюший код примера а то ошибки когда последний код вставляю Error:(22, 53) error: cannot find symbol class SimpleWebViewClientImpl
Обновил статью ссылкой на исходный код проекта.
При работе только с WebView выдает следующую ошибку при наведении на любую строку с «WebView»: <>. Весь код делал как у вас, все переменные, разрешения прописаны.
Сама ошибка: Cannot resolve symbol WebView. даже в строчке private WebView webView тоже выдает эту ошибку.
Здравствуйте! Скорее всего Ваш проект еще не собран, попробуйте воспользоваться кнопкой Build в среде разработки Android Studio и затем запустить с помощью кнопки Run на устройстве или эмуляторе.
Попробовал. В логе выдает три одинаковые ошибки — error: cannot find symbol class WebView. Указывает на именно те строчки, где прописано WebView. Не компилируется только файл MainActivity.java, все остальное вроде работает.
These topics are so coinsufng but this helped me get the job done.
Кое-что изменилось. Ошибки пропали, но теперь вместо отображения html страницы из интернета белый экран. Помогите пожалуйста, как исправить
Здравствуйте!
Благодарю Вас за подробный пример, очень пригодился!
Не могли бы Вы подсказать, как определять геолокацию?
Пробовал разные варианты, вроде как даже рабочие по комментам авторов, но они 2013 года, и сейчас не работают, не появляется предложение разрешить геолокацию.
Здравствуйте, что то могло измениться за это время, сохраняю ваш проект с другим урлом, все работает, но все ссылки открываются в браузере, андроид 6, ошибок нет никаких?
Здравствуйте.
Имеется проект с имеющимся андроид приложением. Но имеются проблемы. На сайте имеется функция загрузки и скачивания файлов. На ПК работает всё нормально. На телефоне так же но только через браузер.
Через приложение заливается файл на сервер на ура, а вот скачать не получается.
Так всё отлично и уведомления о письмах от пользователей приходят, и о всех других действиях на сайте. Но нужно решить проблему именно с файлами (загрузка и скачивание с любых версий андроид).
Возможно ли такое осуществить?
У меня все работает, но при вызове методов:
this.webView.canGoBack()
или
this.webView.goBack();
приложение вылетает с ошибкой
«Имя приложения» has stopped
Open app again
Что можно сделать?
Здравствуйте.
Скажите, пожалуйста, а возможно ли в webView.loadUrl указывать поддомен?
Просто беда такая… Был указан домен, все работало. Затем появилась необходимость работы на поддомене, исправил, скомпилировал, заново установил на устройство… теперь приложение открывается, но — белый экран…
Спасибо.