Используйте WebView для отображения веб-приложения или веб-страницы в составе клиентского приложения. Класс WebView является расширением класса View из Android и позволяет отображать веб-страницы в составе макета вашей активности. Он не включает в себя функции полноценного веб-браузера, такие как элементы управления навигацией или адресная строка. По умолчанию WebView просто отображает веб-страницу.
WebView может помочь вам добавить в приложение информацию, которую, возможно, потребуется обновить, например, пользовательское соглашение или руководство пользователя. В вашем Android-приложении вы можете создать Activity , содержащую WebView , а затем использовать её для отображения документа, размещенного в интернете.
WebView также может помочь, когда ваше приложение предоставляет пользователю данные, для получения которых требуется подключение к интернету, например, электронная почта. В этом случае вам может показаться проще создать WebView в вашем Android-приложении, который отображает веб-страницу со всеми данными пользователя, чем выполнять сетевой запрос, затем анализировать данные и отображать их в макете Android. Вместо этого вы можете разработать веб-страницу, адаптированную для устройств на базе Android, а затем реализовать WebView в вашем Android-приложении, который будет загружать эту веб-страницу.
В этом документе описывается, как начать работу с WebView , как привязать JavaScript с вашей веб-страницы к клиентскому коду в вашем Android-приложении, как обрабатывать навигацию по страницам и как управлять окнами при использовании WebView .
Работа с WebView на более ранних версиях Android
Для безопасного использования более новых возможностей WebView на устройстве, на котором работает ваше приложение, добавьте библиотеку AndroidX Webkit . Это статическая библиотека, которую вы можете добавить в свое приложение для использования API android.webkit , недоступных для более ранних версий платформы.
Добавьте это в файл build.gradle следующим образом:
Котлин
dependencies { implementation("androidx.webkit:webkit:1.8.0") }
Классный
dependencies { implementation ("androidx.webkit:webkit:1.8.0") }
Для получения более подробной информации изучите пример WebView на GitHub.
Добавьте WebView в свое приложение.
Чтобы добавить WebView в ваше приложение, вы можете включить элемент <WebView> в макет вашей активности или установить все окно Activity в качестве WebView в onCreate() .
Добавьте WebView в макет активности.
Чтобы добавить WebView в макет вашего приложения, добавьте следующий код в XML-файл макета вашей активности:
<WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_hei>ght="match_parent" /
Для загрузки веб-страницы в WebView используйте loadUrl() , как показано в следующем примере:
Котлин
val myWebView: WebView = findViewById(R.id.webview) myWebView.loadUrl("http://www.example.com")
Java
WebView myWebView = (WebView) findViewById(R.id.webview); myWebView.loadUrl("http://www.example.com");
Добавьте WebView в метод onCreate().
Чтобы добавить WebView в ваше приложение в методе onCreate() активности, используйте логику, аналогичную следующей:
Котлин
val myWebView = WebView(activityContext) setContentView(myWebView)
Java
WebView myWebView = new WebView(activityContext); setContentView(myWebView);
Затем загрузите страницу:
Котлин
myWebView.loadUrl("http://www.example.com")
Java
myWebView.loadUrl("https://www.example.com");
Или загрузите URL-адрес из HTML-строки:
Котлин
// Create an unencoded HTML string, then convert the unencoded HTML string into // bytes. Encode it with base64 and load the data. val unencodedHtml = &<quot><;htm>lbody'%23' is the percent <code ><for ‘>#‘ /body/html"; val encodedHtml = Base64.encodeToString(unencodedHtml.toByteArray(), Base64.NO_PADDING) myWebView.loadData(encodedHtml, "text/html", "base64")
Java
// Create an unencoded HTML string, then convert the unencoded HTML string into // bytes. Encode it with base64 and load the data. String unencodedHtml = &<quot><;htm>lbody'%23' is the percent <code ><for ‘>#‘ /body/html"; String encodedHtml = Base64.encodeToString(unencodedHtml.getBytes(), Base64.NO_PADDING); myWebView.loadData(encodedHtml, "text/html", "base64");
Вашему приложению необходим доступ к интернету. Для получения доступа к интернету запросите разрешение INTERNET в файле манифеста, как показано в следующем примере:
<manifest ... > <uses-permission android:name="android.permission.INTERN>ET" </ ...> /manifest
Вы можете настроить WebView , выполнив одно из следующих действий:
- Включение полноэкранного режима с помощью
WebChromeClient. Этот класс также вызывается, когдаWebViewтребуется разрешение на изменение пользовательского интерфейса хост-приложения, например, на создание или закрытие окон или отправку диалоговых окон JavaScript пользователю. Для получения дополнительной информации об отладке в этом контексте см. раздел «Отладка веб-приложений» . - Обработка событий, влияющих на отображение контента, таких как ошибки при отправке форм или навигации, с помощью
WebViewClient. Вы также можете использовать этот подкласс для перехвата загрузки URL-адресов. - Включение JavaScript путем изменения
WebSettings. - Использование JavaScript для доступа к объектам фреймворка Android, внедренным в
WebView.
Использование JavaScript в WebView
Если веб-страница, которую вы хотите загрузить в WebView , использует JavaScript, вам необходимо включить JavaScript для вашего WebView . После включения JavaScript вы сможете создавать интерфейсы между кодом вашего приложения и кодом JavaScript.
Включить JavaScript
В WebView по умолчанию JavaScript отключен. Вы можете включить его через WebSettings прикрепленные к вашему WebView . Получите WebSettings с помощью getSettings() , а затем включите JavaScript с помощью setJavaScriptEnabled() .
См. следующий пример:
Котлин
val myWebView: WebView = findViewById(R.id.webview) myWebView.settings.javaScriptEnabled = true
Java
WebView myWebView = (WebView) findViewById(R.id.webview); WebSettings webSettings = myWebView.getSettings(); webSettings.setJavaScriptEnabled(true);
WebSettings предоставляет доступ к множеству других настроек, которые могут оказаться полезными. Например, если вы разрабатываете веб-приложение, специально предназначенное для WebView в вашем Android-приложении, вы можете определить пользовательскую строку User Agent с помощью setUserAgentString() , а затем запросить этот пользовательский агент на вашей веб-странице, чтобы убедиться, что клиент, запрашивающий вашу веб-страницу, является вашим Android-приложением.
Привязка кода JavaScript к коду Android
При разработке веб-приложения, специально предназначенного для использования WebView в вашем Android-приложении, вы можете создавать интерфейсы между вашим JavaScript-кодом и клиентским Android-кодом. Например, ваш JavaScript-код может вызывать метод в вашем Android-коде для отображения Dialog , вместо использования функции alert() в JavaScript.
Чтобы связать новый интерфейс между вашим JavaScript-кодом и кодом Android, вызовите addJavascriptInterface() , передав ему экземпляр класса для привязки к вашему JavaScript-коду и имя интерфейса, к которому ваш JavaScript сможет обращаться для доступа к классу.
Например, вы можете включить следующий класс в свое Android-приложение:
Котлин
/** 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() } }
Java
public class WebAppInterface { Context mContext; /** Instantiate the interface and set the context. */ WebAppInterface(Context c) { mContext = c; } /** Show a toast from the web page. */ @JavascriptInterface public void showToast(String toast) { Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show(); } }
В этом примере класс WebAppInterface позволяет веб-странице создавать Toast ) с помощью метода showToast() .
Вы можете связать этот класс с JavaScript-кодом, который выполняется в вашем WebView с помощью addJavascriptInterface() , как показано в следующем примере:
Котлин
val webView: WebView = findViewById(R.id.webview) webView.addJavascriptInterface(WebAppInterface(this), "Android")
Java
WebView webView = (WebView) findViewById(R.id.webview); webView.addJavascriptInterface(new WebAppInterface(this), "Android");
Это создаёт интерфейс под названием Android для JavaScript, работающий в WebView . На этом этапе ваше веб-приложение получает доступ к классу WebAppInterface . Например, вот фрагмент HTML и JavaScript, который создаёт всплывающее сообщение с использованием нового интерфейса, когда пользователь нажимает кнопку:
<input type="button" value="Say hello" onClick="showAndroidT>oa<st('Hello Android!')&>quot; / script type="text/javascript" function showAndroidToast(t<oast) {> Android.showToast(toast); } /script
Нет необходимости инициализировать интерфейс Android из JavaScript. WebView автоматически предоставляет его вашей веб-странице. Таким образом, когда пользователь нажимает кнопку, функция showAndroidToast() использует интерфейс Android для вызова метода WebAppInterface.showToast() .
Обработка навигации по страницам
Когда пользователь переходит по ссылке с веб-страницы в вашем WebView , по умолчанию Android запускает приложение, обрабатывающее URL-адреса. Обычно открывается и загружается целевой URL-адрес веб-браузером по умолчанию. Однако вы можете изменить это поведение для вашего WebView , чтобы ссылки открывались внутри вашего WebView . Затем вы можете позволить пользователю перемещаться вперед и назад по истории посещенных веб-страниц, которая хранится в вашем WebView .
Чтобы открыть ссылки, на которые нажимает пользователь, предоставьте WebViewClient для вашего WebView , используя setWebViewClient() . Все ссылки, на которые нажимает пользователь, загружаются в ваш WebView . Если вы хотите больше контролировать, куда загружается нажатая ссылка, создайте свой собственный WebViewClient , который переопределяет метод shouldOverrideUrlLoading() . В следующем примере предполагается, что MyWebViewClient является внутренним классом Activity .
Котлин
private class MyWebViewClient : WebViewClient() { override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { if (Uri.parse(url).host == "www.example.com") { // This is your website, so don't override. Let your WebView load // the page. return false } // Otherwise, the link isn't for a page on your site, so launch another // Activity that handles URLs. Intent(Intent.ACTION_VIEW, Uri.parse(url)).apply { startActivity(this) } return true } }
Java
private class MyWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { if ("www.example.com".equals(request.getUrl().getHost())) { // This is your website, so don't override. Let your WebView load the // page. return false; } // Otherwise, the link isn't for a page on your site, so launch another // Activity that handles URLs. Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl()); startActivity(intent); return true; } }
Затем создайте экземпляр этого нового WebViewClient для WebView :
Котлин
val myWebView: WebView = findViewById(R.id.webview) myWebView.webViewClient = MyWebViewClient()
Java
WebView myWebView = (WebView) findViewById(R.id.webview); myWebView.setWebViewClient(new MyWebViewClient());
Теперь, когда пользователь нажимает на ссылку, система вызывает метод shouldOverrideUrlLoading() , который проверяет, соответствует ли хост URL определенному домену, как определено в предыдущем примере. Если он соответствует, метод возвращает false и не переопределяет загрузку URL. Он позволяет WebView загрузить URL как обычно. Если хост URL не соответствует, создается Intent для запуска Activity по умолчанию для обработки URL, которая обращается к веб-браузеру пользователя по умолчанию.
Обработка пользовательских URL-адресов
WebView применяет ограничения при запросе ресурсов и разрешении ссылок, использующих пользовательскую схему URL. Например, если вы реализуете обратные вызовы, такие как shouldOverrideUrlLoading() или shouldInterceptRequest() , то WebView будет вызывать их только для допустимых URL-адресов.
Например, WebView может не вызывать ваш метод shouldOverrideUrlLoading() для ссылок следующего вида:
<a href="showPro>file"Sh<ow> Profile/a
Недействительные URL-адреса, подобные показанному в предыдущем примере, обрабатываются в WebView непоследовательно, поэтому мы рекомендуем использовать вместо них корректный URL-адрес. Вы можете использовать пользовательскую схему или URL-адрес HTTPS для домена, контролируемого вашей организацией.
Вместо использования простой строки в ссылке, как в предыдущем примере, вы можете использовать пользовательскую схему, например, следующую:
<a href="example-app:showPro>file"Sh<ow> Profile/a
Затем вы можете обработать этот URL-адрес в методе shouldOverrideUrlLoading() следующим образом:
Котлин
// The URL scheme must be non-hierarchical, meaning no trailing slashes. const val APP_SCHEME = "example-app:" override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { return if (url?.startsWith(APP_SCHEME) == true) { urlData = URLDecoder.decode(url.substring(APP_SCHEME.length), "UTF-8") respondToData(urlData) true } else { false } }
Java
// The URL scheme must be non-hierarchical, meaning no trailing slashes. private static final String APP_SCHEME = "example-app:"; @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith(APP_SCHEME)) { urlData = URLDecoder.decode(url.substring(APP_SCHEME.length()), "UTF-8"); respondToData(urlData); return true; } return false; }
API ` shouldOverrideUrlLoading() в первую очередь предназначен для запуска интентов для определенных URL-адресов. При его реализации убедитесь, что для обрабатываемых WebView URL-адресов возвращается false . Однако вы не ограничены запуском интентов. Вы можете заменить запуск интентов любым пользовательским поведением, описанным в приведенных выше примерах кода.
Перейти к истории веб-страниц
Когда ваш WebView переопределяет загрузку URL-адреса, он автоматически накапливает историю посещенных веб-страниц. Вы можете перемещаться назад и вперед по этой истории с помощью goBack() и goForward() .
Например, ниже показано, как ваше Activity может использовать кнопку «Назад» на устройстве для возврата назад:
Котлин
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { // Check whether the key event is the Back button and if there's history. if (keyCode == KeyEvent.KEYCODE_B&&ACK myWebView.canGoBack()) { myWebView.goBack() return true } // If it isn't the Back button or there isn't web page history, bubble up to // the default system behavior. Probably exit the activity. return super.onKeyDown(keyCode, event) }
Java
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { // Check whether the key event is the Back button and if there's history. if ((keyCode == KeyEvent.KEYCODE_BA&&CK) myWebView.canGoBack()) { myWebView.goBack(); return true; } // If it isn't the Back button or there's no web page history, bubble up to // the default system behavior. Probably exit the activity. return super.onKeyDown(keyCode, event); }
Если ваше приложение использует AndroidX AppCompat 1.6.0+, вы можете еще больше упростить предыдущий фрагмент кода:
Котлин
onBackPressedDispatcher.addCallback { // Check whether there's history. if (myWebView.canGoBack()) { myWebView.goBack() } }
Java
onBackPressedDispatcher.addCallback { // Check whether there's history. if (myWebView.canGoBack()) { myWebView.goBack(); } }
Метод canGoBack() возвращает true, если у пользователя есть история посещений веб-страниц. Аналогично, вы можете использовать canGoForward() для проверки наличия истории перемотки вперед. Если вы не выполняете эту проверку, то после того, как пользователь достигнет конца истории, goBack() и goForward() ничего не делают.
Обработка изменений конфигурации устройства
Во время выполнения программы изменения состояния активности происходят при изменении конфигурации устройства, например, когда пользователь поворачивает устройство или закрывает редактор методов ввода (IME). Эти изменения приводят к уничтожению активности объекта WebView и созданию новой активности, которая также создает новый объект WebView , загружающий URL-адрес уничтоженного объекта. Чтобы изменить поведение активности по умолчанию, вы можете изменить способ обработки изменений orientation в вашем манифесте. Чтобы узнать больше об обработке изменений конфигурации во время выполнения, прочитайте раздел «Обработка изменений конфигурации» .
Управление окнами
По умолчанию запросы на открытие новых окон игнорируются. Это справедливо как для окон, открываемых с помощью JavaScript, так и для окон, открываемых атрибутом target в ссылке. Вы можете настроить WebChromeClient , чтобы задать собственное поведение при открытии нескольких окон одновременно.
Для повышения безопасности вашего приложения лучше всего предотвратить открытие всплывающих окон и новых окон. Самый безопасный способ реализовать это поведение — передать значение "true" в метод setSupportMultipleWindows() , но не переопределять метод onCreateWindow() , от которого зависит setSupportMultipleWindows() . Эта логика предотвращает загрузку любой страницы, в ссылках которой используется target="_blank" .