Android. WebView i loadData

105

Możliwe jest użycie następującej metody do ustawienia zawartości loadData widoku internetowego (String data, String mimeType, String encoding)

Jak sobie radzić z nieznanym kodowaniem danych html ?!

Czy jest lista kodowań ?!

Wiem z uczelni, że w moim przypadku html pochodzi z DB i jest kodowany za pomocą latin-1. Próbuję ustawić parametr kodowania na latin-1, na ISO-8859-1 / iso-8859-1, ale nadal mam problem z wyświetlaniem znaków specjalnych, takich jak ä, ö, ü.

Będę bardzo wdzięczny za każdą radę.

Tima
źródło

Odpowiedzi:

206
myWebView.loadData(myHtmlString, "text/html; charset=UTF-8", null);

Działa to bezbłędnie, szczególnie w systemie Android 4.0, który najwyraźniej ignoruje kodowanie znaków w HTML.

Testowany na 2.3 i 4.0.3.

W rzeczywistości nie mam pojęcia, jakie inne wartości oprócz „base64” przyjmuje ostatni parametr. Niektóre przykłady Google zawierają tam wartość null.

patryk
źródło
2
Nie może to działać „bezbłędnie”, jeśli masz znaki spoza zestawu znaków US-ASCII.
Andrey Novikov
1
Właśnie wypróbowałem na urządzeniu 4.2.2 i działa jak urok, ale na urządzeniu 2.3.6 pokazuje tylko te same śmieci. : S
Frank
Działa to również w przypadku mnie w 4.1.2 (który również ignoruje zestaw znaków w HTML) iz kodowaniem Latin1! Domyśl.
Luis A. Florit,
2
@Frank To samo tutaj, testowałem na HTC one 2.3.7 (prawdopodobnie wszystkie pierniki) i dostałem te same śmieci, muszę użyć rozwiązania Andrey Novikov zWebView.loadDataWithBaseURL()
ForceMagic
Jaka jest różnica między Twoją odpowiedzią a: myWebView.loadData (myHtmlString, "text / html", "UTF-8");
Lou Morda
135

WebView.loadData () w ogóle nie działa poprawnie. Musiałem zrobić:

String header = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>";
myWebView.loadData(header+myHtmlString, "text/html", "UTF-8");

Myślę, że w twoim przypadku powinieneś zamienić UTF-8 na latin1 lub ISO-8859-1 zarówno w nagłówku, jak iw WebView.loadData ().

Aby udzielić pełnej odpowiedzi, oto oficjalna lista kodowań: http://www.iana.org/ assignments/character- sets

Aktualizuję odpowiedź, aby była bardziej inkluzywna:

Aby użyć WebView.loadData () z kodowaniem innym niż latin1, musisz zakodować zawartość html. Poprzedni przykład nie działał poprawnie w systemie Android 4+, więc zmodyfikowałem go tak, aby wyglądał następująco:

WebSettings settings = myWebView.getSettings();
settings.setDefaultTextEncodingName("utf-8");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
    String base64 = Base64.encodeToString(htmlString.getBytes(), Base64.DEFAULT);
    myWebView.loadData(base64, "text/html; charset=utf-8", "base64");
} else {
    String header = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>";
    myWebView.loadData(header + htmlString, "text/html; charset=UTF-8", null);

}

Ale później przeszedłem na WebView.loadDataWithBaseURL () i kod stał się bardzo czysty i nie zależał od wersji Androida:

WebSettings settings = myWebView.getSettings();
settings.setDefaultTextEncodingName("utf-8");
myWebView.loadDataWithBaseURL(null, htmlString, "text/html", "utf-8", null);

Z jakiegoś powodu te funkcje mają zupełnie inną implementację.

Andrey Novikov
źródło
1
Privet, Andrey. Wypróbowałem twoje rozwiązanie. Niestety to nie zadziałało :(
Tima
Czy wypróbowałeś UTF-8, jak opisałem? Kiedy myślę o twoim pytaniu, przychodzi mi do głowy, że w Javie wszystkie ciągi są w UTF-8, więc mój przykład powinien działać nienaruszony.
Andrey Novikov
Wszystkie ciągi znaków to UTF-8, ale tekst pochodzący z serwera jest zapisany w języku łacińskim-1. Myślę, że próbowałem z UTF-8 i latin-1 iz ISO-8859-1, ale nadal widziałem dziwne znaki zamiast ü, ö, ä. Ale mam inny pomysł, spróbuję przekonwertować strumień bajtów z serwera na ciąg przy użyciu odpowiedniego kodowania. może to mi pomoże
Tima
4
w wersji 4.0+ kodowanie powinno być również ustawione w typie MIME „text / html; chartset = utf-8”, w przeciwnym razie nie zostanie rozpoznane
marwinXXII
2
Ostatni fragment (ten z loadDataWithBaseURL) działa świetnie zarówno na urządzeniach 4.2.2, jak i 2.3.6: D
Frank,
36

Jak rozumiem, loadData()po prostu generuje plikdata: adres URL z dostarczonymi danymi.

Przeczytaj javadocs dla loadData():

Jeśli wartością parametru kodowania jest „base64”, dane muszą być zakodowane jako base64. W przeciwnym razie dane muszą używać kodowania ASCII dla oktetów w zakresie bezpiecznych znaków adresu URL i używać standardowego kodowania szesnastkowego% xx adresów URL dla oktetów spoza tego zakresu. Na przykład, '#', '%', '\', '?' należy zastąpić odpowiednio% 23,% 25,% 27,% 3f.

Adres URL schematu danych utworzony tą metodą używa domyślnego zestawu znaków US-ASCII. Jeśli potrzebujesz ustawić inny zestaw znaków, powinieneś utworzyć adres URL schematu danych, który wyraźnie określa parametr zestawu znaków w części typu mediatype adresu URL i zamiast tego wywołać loadUrl (String). Zwróć uwagę, że zestaw znaków uzyskany z części adresu URL danych określającej typ nośnika zawsze zastępuje ten określony w samym dokumencie HTML lub XML.

Dlatego powinieneś albo użyć US-ASCII i samodzielnie uciec przed znakami specjalnymi, albo po prostu zakodować wszystko za pomocą Base64. Poniższe powinno działać, zakładając, że używasz UTF-8 (nie testowałem tego z latin1):

String data = ...;  // the html data
String base64 = android.util.Base64.encodeToString(data.getBytes("UTF-8"), android.util.Base64.DEFAULT);
webView.loadData(base64, "text/html; charset=utf-8", "base64");
Ralf
źródło
To przypomniało mi o sprawdzeniu dokumentacji przed wędrowaniem wszędzie!
Pradeep
Dziękuję za odpowiedź! Wczytywał inną wbudowaną pomoc kontekstową HTML w widoku sieci Web i działało tylko przez pewien czas. To naprawiło.
eric
20

Mam ten problem, ale:

String content = "<html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" /></head><body>";
content += mydata + "</body></html>";
WebView1.loadData(content, "text/html", "UTF-8");

nie działa na wszystkich urządzeniach. I łączę kilka metod:

String content = 
       "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"+
       "<html><head>"+
       "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />"+
       "</head><body>";

content += myContent + "</body></html>";

WebView WebView1 = (WebView) findViewById(R.id.webView1);
WebView1.loadData(content, "text/html; charset=utf-8", "UTF-8");

To działa.

Aloyan Dmitry
źródło
NIE jest to zalecane przez Google. Zobacz moją odpowiedź i SPRAWDŹ rozmowę wideo ;-) stackoverflow.com/questions/3961589/…
Pascal
7

użyj tego: String customHtml = text;

           wb.loadDataWithBaseURL(null,customHtml,"text/html", "UTF-8", null);
krishna
źródło
15 post później i tylko ten działał dla mnie
Guy Cothal
5
 String strWebData="html...." //**Your html string**

 WebView webDetail=(WebView) findViewById(R.id.webView1);

 WebSettings websetting = webDetail.getSettings();

 websetting.setDefaultTextEncodingName("utf-8");

 webDetail.loadData(strWebData, "text/html; charset=utf-8", null);
Yiğit
źródło
5

Najbezpieczniejszym sposobem, aby załadować htmlContent w widoku sieci Web jest:

  1. użyj kodowania base64 (oficjalne zalecenie)
  2. określ UFT-8 dla typu treści html, np. „text / html; charset = utf-8” zamiast „text / html” (osobista porada)

„Kodowanie Base64” to oficjalna rekomendacja, która została napisana ponownie (już obecna w Javadoc) w najnowszym błędzie 01/2019 w Chrmium (obecny w WebView M72 (72.0.3626.76)):

https://bugs.chromium.org/p/chromium/issues/detail?id=929083

Oficjalne oświadczenie zespołu Chromium:

„Zalecana poprawka:
nasz zespół zaleca kodowanie danych za pomocą Base64. Podaliśmy przykłady, jak to zrobić:

Ta poprawka jest kompatybilna wstecz (działa we wcześniejszych wersjach WebView) i powinna być również przyszłościowa (nie napotkasz przyszłych problemów ze zgodnością w odniesieniu do kodowania treści). "

Przykład kodu:

webView.loadData(
    Base64.encodeToString(
        htmlContent.getBytes(StandardCharsets.UTF_8),
        Base64.DEFAULT), // encode in Base64 encoded 
    "text/html; charset=utf-8", // utf-8 html content (personal recommendation)
    "base64"); // always use Base64 encoded data: NEVER PUT "utf-8" here (using base64 or not): This is wrong! 
Pascal
źródło
1

powyższe odpowiedzi nie działają w moim przypadku. Musisz określić utf-8 w metatagu

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    </head>
    <body>
        <!-- you content goes here -->
    </body>
</html>
Truong Nguyen
źródło
-1

webview.loadDataWithBaseURL (null, text, "text / html", "UTF-8", null);

Celal Kanat
źródło