Вы можете предоставить веб-контент, такой как HTML, JavaScript и CSS, для использования в вашем приложении, который вы статически компилируете в приложение, а не загружаете через Интернет.
Контент в приложении не требует доступа в Интернет и не потребляет пропускную способность пользователя. Если контент разработан специально только для WebView
, то есть зависит от взаимодействия с собственным приложением, пользователи не смогут случайно загрузить его в веб-браузер.
Однако у контента внутри приложения есть некоторые недостатки. Обновление веб-контента требует отправки нового обновления приложения, и существует вероятность несоответствия содержимого между тем, что находится на веб-сайте, и тем, что находится в приложении на вашем устройстве, если у пользователей устаревшие версии приложения.
Вебвиевассетлоадер
WebViewAssetLoader
— это гибкий и эффективный способ загрузки содержимого приложения в объект WebView
. Этот класс поддерживает следующее:
- Загрузка контента с помощью URL-адреса HTTP(S) для совместимости с политикой одного и того же источника .
- Загрузка подресурсов, таких как JavaScript, CSS, изображения и iframe.
Включите WebViewAssetLoader
в свой основной файл активности. Ниже приведен пример загрузки простого веб-содержимого из папки ресурсов:
Котлин
private class LocalContentWebViewClient(private val assetLoader: WebViewAssetLoader) : WebViewClientCompat() { @RequiresApi(21) override fun shouldInterceptRequest( view: WebView, request: WebResourceRequest ): WebResourceResponse? { return assetLoader.shouldInterceptRequest(request.url) } // To support API < 21. override fun shouldInterceptRequest( view: WebView, url: String ): WebResourceResponse? { return assetLoader.shouldInterceptRequest(Uri.parse(url)) } }
Ява
private static class LocalContentWebViewClient extends WebViewClientCompat { private final WebViewAssetLoader mAssetLoader; LocalContentWebViewClient(WebViewAssetLoader assetLoader) { mAssetLoader = assetLoader; } @Override @RequiresApi(21) public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { return mAssetLoader.shouldInterceptRequest(request.getUrl()); } @Override @SuppressWarnings("deprecation") // To support API < 21. public WebResourceResponse shouldInterceptRequest(WebView view, String url) { return mAssetLoader.shouldInterceptRequest(Uri.parse(url)); } }
Ваше приложение должно настроить экземпляр WebViewAssetLoader
в соответствии со своими потребностями. В следующем разделе есть пример.
Создавайте ресурсы и ресурсы внутри приложения
WebViewAssetLoader
использует экземпляры PathHandler
для загрузки ресурсов, соответствующих заданному пути к ресурсу. Хотя вы можете реализовать этот интерфейс для получения ресурсов по мере необходимости вашего приложения, библиотека Webkit объединяет AssetsPathHandler
и ResourcesPathHandler
для загрузки ресурсов и ресурсов Android соответственно.
Для начала создайте активы и ресурсы для своего приложения. Обычно применяется следующее:
- Текстовые файлы, такие как HTML, JavaScript и CSS, относятся к ресурсам.
- Изображения и другие двоичные файлы относятся к ресурсам.
Чтобы добавить в проект текстовые веб-файлы, выполните следующие действия:
- В Android Studio щелкните правой кнопкой мыши приложение > src > основная папка и выберите «Создать» > «Каталог» .
- Назовите папку «активы».
- Щелкните правой кнопкой мыши папку ресурсов и выберите «Создать» > «Файл» . Введите
index.html
и нажмите клавишу Return или Enter . - Повторите предыдущий шаг, чтобы создать пустой файл
stylesheet.css
. - Заполните созданные пустые файлы содержимым следующих двух примеров кода.
```html
<!-- index.html content -->
<html>
<head>
<!-- Tip: Use relative URLs when referring to other in-app content to give
your app code the flexibility to change the scheme or domain as
necessary. -->
<link rel="stylesheet" href="/assets/stylesheet.css">
</head>
<body>
<p>This file is loaded from in-app content.</p>
<p><img src="/res/drawable/android_robot.png" alt="Android robot" width="100"></p>
</body>
</html>
```
```css
<!-- stylesheet.css content -->
body {
background-color: lightblue;
}
```
Чтобы добавить в проект веб-файл на основе изображения, выполните следующие действия:
Загрузите файл
Android_symbol_green_RGB.png
на свой локальный компьютер.Переименуйте файл в
android_robot.png
.Вручную переместите файл в каталог
main/res/drawable
вашего проекта на жестком диске.
На рис. 4 показано добавленное вами изображение и текст из предыдущих примеров кода, отображаемый в приложении.
Чтобы завершить работу приложения, выполните следующие действия:
Зарегистрируйте обработчики и настройте
AssetLoader
, добавив следующий код в методonCreate()
:Котлин
val assetLoader = WebViewAssetLoader.Builder() .addPathHandler("/assets/", AssetsPathHandler(this)) .addPathHandler("/res/", ResourcesPathHandler(this)) .build() webView.webViewClient = LocalContentWebViewClient(assetLoader)
Ява
final WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder() .addPathHandler("/assets/", new WebViewAssetLoader.AssetsPathHandler(this)) .addPathHandler("/res/", new WebViewAssetLoader.ResourcesPathHandler(this)) .build(); mWebView.setWebViewClient(new LocalContentWebViewClient(assetLoader));
Загрузите содержимое, добавив следующий код в метод
onCreate()
:Котлин
webView.loadUrl("https://appassets.androidplatform.net/assets/index.html")
Ява
mWebView.loadUrl("https://appassets.androidplatform.net/assets/index.html");
Смешайте контент внутри приложения с ресурсами вашего сайта.
Вашему приложению может потребоваться загрузить как контент из приложения, так и контент из Интернета, например HTML-страницу внутри приложения, оформленную с помощью CSS вашего веб-сайта. WebViewAssetLoader
поддерживает этот вариант использования. Если ни один из зарегистрированных экземпляров PathHandler
не может найти ресурс по данному пути, WebView
возвращается к загрузке контента из Интернета. Если вы смешиваете контент приложения с ресурсами своего веб-сайта, зарезервируйте пути к каталогам, например /assets/
или /resources/
, для ресурсов приложения. Избегайте хранения каких-либо ресурсов вашего веб-сайта в этих местах.
Котлин
val assetLoader = WebViewAssetLoader.Builder() .setDomain("example.com") // Replace this with your website's domain. .addPathHandler("/assets/", AssetsPathHandler(this)) .build() webView.webViewClient = LocalContentWebViewClient(assetLoader) val inAppHtmlUrl = "https://example.com/assets/index.html" webView.loadUrl(inAppHtmlUrl) val websiteUrl = "https://example.com/website/data.json" // JavaScript code to fetch() content from the same origin. val jsCode = "fetch('$websiteUrl')" + ".then(resp => resp.json())" + ".then(data => console.log(data));" webView.evaluateJavascript(jsCode, null)
Ява
final WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder() .setDomain("example.com") // Replace this with your website's domain. .addPathHandler("/assets/", new AssetsPathHandler(this)) .build(); mWebView.setWebViewClient(new LocalContentWebViewClient(assetLoader)); String inAppHtmlUrl = "https://example.com/assets/index.html"; mWebView.loadUrl(inAppHtmlUrl); String websiteUrl = "https://example.com/website/data.json"; // JavaScript code to fetch() content from the same origin. String jsCode = "fetch('" + websiteUrl + "')" + ".then(resp => resp.json())" + ".then(data => console.log(data));"; mWebView.evaluateJavascript(jsCode, null);
См. демонстрацию WebView
на GitHub, где приведен пример HTML-страницы в приложении, извлекающей данные JSON, размещенные в Интернете.
ЗагрузитьДанныеВиБасеURL
Если вашему приложению нужно только загрузить HTML-страницу и не нужно перехватывать подресурсы, рассмотрите возможность использования loadDataWithBaseURL()
, для которого не требуются ресурсы приложения. Вы можете использовать его, как показано в следующем примере кода:
Котлин
val html = "<html><body><p>Hello world</p></body></html>" val baseUrl = "https://example.com/" webView.loadDataWithBaseURL(baseUrl, html, "text/html", null, baseUrl)
Ява
String html = "<html><body><p>Hello world</p></body></html>"; String baseUrl = "https://example.com/"; mWebView.loadDataWithBaseURL(baseUrl, html, "text/html", null, baseUrl);
Тщательно выбирайте значения аргументов. Учтите следующее:
-
baseUrl
: это URL-адрес, по которому загружается ваш HTML-контент. Это должен быть URL-адрес HTTP(S). -
data
: это HTML-содержимое, которое вы хотите отобразить в виде строки. -
mimeType
: обычно должно быть установлено значениеtext/html
. -
encoding
: не используется, еслиbaseUrl
является URL-адресом HTTP(S), поэтому для него можно установить значениеnull
. -
historyUrl
: для него установлено то же значение, что иbaseUrl
.
Мы настоятельно рекомендуем использовать URL-адрес HTTP(S) в качестве baseUrl
, поскольку это помогает гарантировать, что ваше приложение соответствует политике одного и того же источника.
Если вы не можете найти подходящий baseUrl
для своего контента и предпочитаете использовать loadData()
, вам необходимо закодировать контент с помощью процентной кодировки или кодировки Base64 . Мы настоятельно рекомендуем выбрать кодировку Base64 и использовать API-интерфейсы Android для программного кодирования, как показано в следующем примере кода:
Котлин
val encodedHtml: String = Base64.encodeToString(html.toByteArray(), Base64.NO_PADDING) webView.loadData(encodedHtml, mimeType, "base64")
Ява
String encodedHtml = Base64.encodeToString(html.getBytes(), Base64.NO_PADDING); mWebView.loadData(encodedHtml, mimeType, "base64");
Чего следует избегать
Есть несколько других способов загрузки контента в приложении, но мы настоятельно не рекомендуем их использовать:
-
file://
URL-адреса иdata:
URL-адреса считаются непрозрачными источниками , то есть они не могут использовать преимущества мощных веб-API, таких какfetch()
илиXMLHttpRequest
.loadData()
внутренне используетdata:
URL-адреса, поэтому мы рекомендуем вместо этого использоватьWebViewAssetLoader
илиloadDataWithBaseURL()
. - Хотя
WebSettings.setAllowFileAccessFromFileURLs()
иWebSettings.setAllowUniversalAccessFromFileURLs()
могут обойти проблемы с URL-адресамиfile://
, мы не рекомендуем устанавливать для них значениеtrue
, поскольку это делает ваше приложение уязвимым для файловых эксплойтов. Мы рекомендуем явно установить для них значениеfalse
на всех уровнях API для обеспечения максимальной безопасности. - По тем же причинам мы не рекомендуем использовать URL-адреса
file://android_assets/
иfile://android_res/
. КлассыAssetsHandler
иResourcesHandler
предназначены для замены. - Избегайте использования
MIXED_CONTENT_ALWAYS_ALLOW
. Этот параметр обычно не нужен и ослабляет безопасность вашего приложения. Мы рекомендуем загружать содержимое приложения по той же схеме (HTTP или HTTPS), что и ресурсы вашего веб-сайта, и использоватьMIXED_CONTENT_COMPATIBILITY_MODE
илиMIXED_CONTENT_NEVER_ALLOW
в зависимости от ситуации.