Wczytaj treści w aplikacji

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:

Kotlin

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))
    }
}

Java

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:

  1. W Android Studio kliknij prawym przyciskiem myszy aplikację > src > folder główny a następnie wybierz Nowy > Katalog.
    Obraz przedstawiający menu tworzenia katalogu w Android Studio
    Rysunek 1. Utwórz folder zasobów dla w projektach AI.
  2. Nadaj folderowi nazwę „assets”.
    Obraz przedstawiający folder komponentów
    Rysunek 2. Nazwij folder zasobów.
  3. Kliknij prawym przyciskiem myszy folder assets, a następnie kliknij Nowy > Plik. Wpisz index.html i naciśnij Return lub Enter.
  4. Powtórz poprzedni krok, aby utworzyć pusty plik dla: stylesheet.css
  5. 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:

  1. Pobierz Android_symbol_green_RGB.png na komputer lokalny.

  2. Zmień nazwę pliku na android_robot.png.

  3. 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.

Obraz przedstawiający renderowane dane wyjściowe aplikacji
Rysunek 4. Plik HTML i plik obrazu w aplikacji renderowanych w aplikacji.
.
.

Aby to zrobić:

  1. Zarejestruj moduły obsługi i skonfiguruj AssetLoader, dodając ten kod do metody onCreate():

    Kotlin

    val assetLoader = WebViewAssetLoader.Builder()
                           .addPathHandler("/assets/", AssetsPathHandler(this))
                           .addPathHandler("/res/", ResourcesPathHandler(this))
                           .build()
    webView.webViewClient = LocalContentWebViewClient(assetLoader)
    

    Java

    final WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder()
             .addPathHandler("/assets/", new WebViewAssetLoader.AssetsPathHandler(this))
             .addPathHandler("/res/", new WebViewAssetLoader.ResourcesPathHandler(this))
             .build();
    mWebView.setWebViewClient(new LocalContentWebViewClient(assetLoader));
    
  2. Wczytywanie treści przez dodanie tego kodu do metody onCreate():

    Kotlin

    webView.loadUrl("https://appassets.androidplatform.net/assets/index.html")
    

    Java

    mWebView.loadUrl("https://appassets.androidplatform.net/assets/index.html");
    

Łą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.

Kotlin

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)

Java

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:

Kotlin

val html = "<html><body><p>Hello world</p></body></html>"
val baseUrl = "https://example.com/"

webView.loadDataWithBaseURL(baseUrl, html, "text/html", null, baseUrl)

Java

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, gdy baseUrl to adres URL HTTP(S), więc może być ustawiono na null.
  • historyUrl: ustawiona jest taka sama wartość jak baseUrl.

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:

Kotlin

val encodedHtml: String = Base64.encodeToString(html.toByteArray(), Base64.NO_PADDING)

webView.loadData(encodedHtml, mimeType, "base64")

Java

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 jak fetch() lub XMLHttpRequest. loadData() używa wewnętrznie data: adresów URL, dlatego zachęcamy do stosowania WebViewAssetLoader lub loadDataWithBaseURL().
  • Chociaż WebSettings.setAllowFileAccessFromFileURLs() oraz WebSettings.setAllowUniversalAccessFromFileURLs() możesz obejść problemy z adresami URL file://, odradzamy ustawianie na true, ponieważ zwiększa to podatność aplikacji na ataki wykorzystujące luki w zabezpieczeniach. Zalecamy bezpośrednie ustawienie wartości false na wszystkich poziomach interfejsu API .
  • Z tych samych powodów odradzamy korzystanie z tagów file://android_assets/ oraz file://android_res/ adresy URL. AssetsHandler i ResourcesHandler 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 witryny MIXED_CONTENT_COMPATIBILITY_MODE lub MIXED_CONTENT_NEVER_ALLOW, w razie potrzeby.