Możesz udostępniać treści internetowe, np. HTML, JavaScript CSS – na potrzeby aplikacji kompilowany statycznie, a nie niż pobieranie przez internet.
Treści w aplikacji nie wymagają dostępu do internetu i nie obciążą łącza użytkownika. Jeśli
treść jest przeznaczona tylko dla usługi WebView
– to znaczy
zależy od komunikacji z aplikacją natywną – wtedy użytkownicy nie mogą
otwórz go w przeglądarce.
Są jednak pewne wady treści znajdujących się w aplikacji. Aktualizowanie treści internetowych wymaga wysłania nowej aktualizacji aplikacji, co może powodować niezgodność między zawartością strony a zawartością aplikacji na urządzeniu że użytkownicy mają nieaktualne wersje aplikacji.
Komponent WebViewAssetLoader
WebViewAssetLoader
to
elastyczny i wydajny sposób ładowania treści w aplikacji
WebView
. Te zajęcia wspierają:
:
- Wczytywanie treści z adresem URL HTTP(S) w celu zapewnienia zgodności z tagiem same-origin .
- Wczytuję zasoby podrzędne, takie jak JavaScript, CSS, obrazy i elementy iframe.
Uwzględnij WebViewAssetLoader
w głównym pliku aktywności. Oto
przykład wczytywania prostej treści internetowej z folderu zasobów:
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));
}
}
Twoja aplikacja musi skonfigurować instancję WebViewAssetLoader
zgodnie ze swoimi potrzebami.
w następnej sekcji znajdziesz przykład.
Tworzenie komponentów i zasobów w aplikacji
Działanie funkcji WebViewAssetLoader
zależy od
PathHandler
.
w celu wczytywania zasobów odpowiadających danej ścieżce zasobów. Chociaż
może zaimplementować ten interfejs, aby pobierać zasoby zgodnie z potrzebami aplikacji,
Pakiety bibliotek Webkit
AssetsPathHandler
oraz
ResourcesPathHandler
do wczytywania zasobów Androida.
Na początek utwórz zasoby aplikacji. Ogólnie parametr następujące zasady:
- Pliki tekstowe, takie jak HTML, JavaScript i CSS, należą do zasobów.
- Obrazy i inne pliki binarne należą do zasobów.
Aby dodać tekstowe pliki internetowe do projektu, wykonaj te czynności:
- W Android Studio kliknij prawym przyciskiem myszy aplikację > src > folder główny
a następnie wybierz Nowy > Katalog.
Rysunek 1. Utwórz folder zasobów dla w projektach AI. - Nadaj folderowi nazwę „assets”.
Rysunek 2. Nazwij folder zasobów. - Kliknij prawym przyciskiem myszy folder assets, a następnie kliknij Nowy > Plik.
Wpisz
index.html
i naciśnij Return lub Enter.Rysunek 3. Utwórz index.html
. - Powtórz poprzedni krok, aby utworzyć pusty plik dla:
stylesheet.css
- Wypełnij puste pliki utworzone przez siebie przy użyciu zawartości następnych 2 kodów przykłady.
```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;
}
```
Aby dodać do projektu plik internetowy z obrazem, wykonaj te czynności:
Pobierz
Android_symbol_green_RGB.png
na komputer lokalny.Zmień nazwę pliku na
android_robot.png
.Przenieś ręcznie plik do katalogu
main/res/drawable
projektu dysku twardego.
Rysunek 4 przedstawia dodany obraz i tekst z poprzednich przykładów kodu renderowanych w aplikacji.

Aby to zrobić:
Zarejestruj moduły obsługi i skonfiguruj
AssetLoader
, dodając ten kod do metodyonCreate()
: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));Wczytywanie treści przez dodanie tego kodu do metody
onCreate()
:
Łączenie treści w aplikacji z zasobami ze swojej strony internetowej
Być może aplikacja będzie musiała wczytać zarówno zawartość aplikacji, jak i zawartość
np. strona HTML w aplikacji stylizowana na kod CSS Twojej witryny.
WebViewAssetLoader
obsługuje ten przypadek użycia. Jeśli żadna z zarejestrowanych
Liczba instancji, które mogą znaleźć zasób dla określonej ścieżki (PathHandler
), wynosi WebView
do wczytywania treści z internetu. Jeśli połączysz zawartość aplikacji z
zasobów z witryny, zarezerwuj ścieżki do katalogów, np. /assets/
lub
/resources/
na zasoby w aplikacji. Unikaj przechowywania zasobów z
witrynę w tych lokalizacjach.
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);
Zobacz wersję demonstracyjną WebView
w
GitHub
znajdziesz przykład strony HTML w aplikacji, która pobiera dane JSON hostowane w internecie.
loadDataWithBaseURL
Gdy aplikacja musi wczytywać tylko stronę HTML i nie musi przechwytywać
zasobów podrzędnych, rozważ użycie
loadDataWithBaseURL()
które nie wymagają komponentów z linkiem do aplikacji. Można go użyć w sposób pokazany w poniższym kodzie
przykład:
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);
Wartości argumentów dobieraj z rozwagą. Weź pod uwagę następujące kwestie:
baseUrl
: adres URL, pod którym są ładowane treści HTML. Musi to być Adres URL HTTP(S).data
: zawartość HTML, którą chcesz wyświetlić w formie ciągu znaków.mimeType
: zwykle należy ustawić wartośćtext/html
.encoding
: ten element nie jest używany, gdybaseUrl
to adres URL HTTP(S), więc może być ustawiono nanull
.historyUrl
: ustawiona jest taka sama wartość jakbaseUrl
.
Zdecydowanie zalecamy użycie adresu URL HTTP(S) w roli baseUrl
, ponieważ pomaga to
sprawdź, czy Twoja aplikacja jest zgodna z zasadami dotyczącymi tej samej domeny.
Jeśli nie możesz znaleźć odpowiedniego pola baseUrl
dla swoich treści i wolisz użyć
loadData()
,
musisz zakodować treść za pomocą parametru
kodowanie procentowe
lub
Base64
.
Zdecydowanie zalecamy kodowanie Base64 i kodowanie interfejsów API Androida
to automatycznie, jak pokazujemy w tym przykładowym kodzie:
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");
Czego warto unikać
Treści można wczytywać w aplikacji na kilka innych sposobów, ale zdecydowanie zalecamy przeciwko nim:
- Adresy URL typu
file://
i adresy URL (data:
) są uznawane za nieprzejrzyste źródła, co oznacza, że nie mogą korzystać z zaawansowanych interfejsów API, takich jakfetch()
lubXMLHttpRequest
.loadData()
używa wewnętrzniedata:
adresów URL, dlatego zachęcamy do stosowaniaWebViewAssetLoader
lubloadDataWithBaseURL()
. - Chociaż
WebSettings.setAllowFileAccessFromFileURLs()
orazWebSettings.setAllowUniversalAccessFromFileURLs()
możesz obejść problemy z adresami URLfile://
, odradzamy ustawianie natrue
, ponieważ zwiększa to podatność aplikacji na ataki wykorzystujące luki w zabezpieczeniach. Zalecamy bezpośrednie ustawienie wartościfalse
na wszystkich poziomach interfejsu API . - Z tych samych powodów odradzamy korzystanie z tagów
file://android_assets/
orazfile://android_res/
adresy URL.AssetsHandler
iResourcesHandler
klasy są zwykłymi zamiennikami. - Unikaj stosowania
MIXED_CONTENT_ALWAYS_ALLOW
To ustawienie zwykle nie jest konieczne i zmniejsza bezpieczeństwo aplikacji. Zalecamy ładowanie treści w aplikacji, korzystając z tego samego schematu – HTTP lub HTTPS – jako zasoby witrynyMIXED_CONTENT_COMPATIBILITY_MODE
lubMIXED_CONTENT_NEVER_ALLOW
, w razie potrzeby.