Android. WebView и loadData


105

Можно использовать следующий метод для настройки содержимого loadData веб-представления (String data, String mimeType, String encoding)

Как решить проблему с неизвестной кодировкой html-данных ?!

А есть список кодировок ?!

Из своего колледжа я знаю, что в моем случае html поступает из БД и закодирован латинским-1. Я пытаюсь установить параметр кодировки на latin-1, на ISO-8859-1 / iso-8859-1, но все еще проблема с отображением специальных знаков, таких как ä, ö, ü.

Буду очень благодарен за любой совет.

Ответы:


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

Это работает безупречно, особенно на Android 4.0, который явно игнорирует кодировку символов внутри HTML.

Проверено на 2.3 и 4.0.3.

Фактически, я понятия не имею о том, какие другие значения, кроме base64, принимает последний параметр. Некоторые примеры Google помещают туда null.


2
Это не может работать "безупречно", если у вас есть символы вне кодировки US-ASCII.
Андрей Новиков

1
Просто попробовал на устройстве 4.2.2 и работает как шарм, но на устройстве 2.3.6 он просто показывает те же символы мусора. : S
Фрэнк

Это также работает для меня в 4.1.2 (который также игнорирует кодировку внутри HTML) и с кодировкой Latin1! Иди разбери.
Луис А. Флорит

2
@Frank То же самое, тестировал на HTC one 2.3.7 (вероятно, все пряники) и получил такую ​​же фигню, я должен использовать решение Андрея Новикова сWebView.loadDataWithBaseURL()
ForceMagic

В чем разница между вашим ответом и: myWebView.loadData (myHtmlString, «text / html», «UTF-8»);
Лу Морда,

135

WebView.loadData () вообще не работает должным образом. Что мне нужно было сделать:

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

Я думаю, что в вашем случае вам следует заменить UTF-8 на latin1 или ISO-8859-1 как в заголовке, так и в WebView.loadData ().

И, чтобы дать полный ответ, вот официальный список кодировок: http://www.iana.org/assignments/character-sets

Я обновляю свой ответ, чтобы он был более содержательным:

Чтобы использовать WebView.loadData () с кодировками, отличными от latin1, вам необходимо закодировать html-контент. Предыдущий пример некорректно работал в Android 4+, поэтому я изменил его, чтобы он выглядел следующим образом:

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

}

Но позже я переключился на WebView.loadDataWithBaseURL (), и код стал очень чистым и не зависел от версии Android:

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

Почему-то у этих функций совершенно разная реализация.


1
Бирючина, Андрей. Я пробовал твое решение. К сожалению, у меня это не сработало :(
Tima

Вы пробовали UTF-8, как я описал? Теперь, когда я думаю о вашем вопросе, мне приходит в голову, что в Java все строки находятся в UTF-8, поэтому мой пример должен работать без изменений.
Андрей Новиков

Все строки в кодировке UTF-8, но текст, поступающий с сервера, имеет латинский-1. Думаю, я пробовал с UTF-8, latin-1 и ISO-8859-1, но все еще видел странные знаки вместо ü, ö, ä. Но у меня есть другая идея, я попробую преобразовать поток байтов с сервера в строку, используя правильную кодировку. может быть, это поможет мне
Тима

4
в кодировке 4.0+ также следует указать тип mime "text / html; chartset = utf-8", иначе он не будет распознан
marwinXXII

2
Последний фрагмент (тот, что с loadDataWithBaseURL) отлично работает как на устройствах 4.2.2, так и на 2.3.6: D
Фрэнк

36

Насколько я понимаю, loadData()просто генерирует data:URL с предоставленными данными.

Прочтите javadocs для loadData():

Если значение параметра кодирования - base64, то данные должны быть закодированы как base64. В противном случае данные должны использовать кодировку ASCII для октетов внутри диапазона безопасных символов URL и использовать стандартную шестнадцатеричную кодировку% xx URL для октетов вне этого диапазона. Например, '#', '%', '\', '?' следует заменить на% 23,% 25,% 27,% 3f соответственно.

URL-адрес схемы данных, сформированный этим методом, использует кодировку US-ASCII по умолчанию. Если вам нужно установить другую кодировку, вы должны сформировать URL-адрес схемы данных, который явно указывает параметр кодировки в части URL-адреса mediatype и вместо этого вызывает loadUrl (String). Обратите внимание, что кодировка, полученная из части mediatype URL-адреса данных, всегда переопределяет кодировку, указанную в самом документе HTML или XML.

Следовательно, вы должны либо использовать US-ASCII и самостоятельно избегать любых специальных символов, либо просто кодировать все с помощью Base64. Следующее должно работать, если вы используете UTF-8 (я не тестировал это с 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");

Это напомнило мне проверить документацию, прежде чем бродить везде!
Pradeep

Спасибо за ответ! Загружал различную встроенную контекстную html-справку в веб-просмотре, и это работало только некоторое время. Это исправило это.
Эрик

20

У меня такая проблема, но:

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");

работает не на всех устройствах. И объединяю несколько методов:

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");

Оно работает.


Это НЕ то, что рекомендует Google. См. Мой ответ и ОБЯЗАТЕЛЬНО ПРОВЕРЬТЕ видео-разговор ;-) stackoverflow.com/questions/3961589/…
Паскаль

7

используйте это: String customHtml = text;

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

15 постов позже, и это единственный, который у меня сработал
Гай Котал,

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

5

Самый безопасный способ загрузить htmlContent в веб-представление:

  1. использовать кодировку base64 (официальная рекомендация)
  2. укажите UFT-8 для типа содержимого html, т.е. «text / html; charset = utf-8» вместо «text / html» (личный совет)

«Кодировка Base64» - это официальная рекомендация, которая была снова написана (уже присутствует в Javadoc) в последней ошибке 01/2019 в Chrominium (присутствует в WebView M72 (72.0.3626.76)):

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

Официальное заявление команды Chromium:

«Рекомендуемое исправление:
наша команда рекомендует кодировать данные с помощью Base64. Мы предоставили примеры того, как это сделать:

Это исправление имеет обратную совместимость (работает с более ранними версиями WebView) и также должно быть рассчитано на будущее (вы не столкнетесь с будущими проблемами совместимости в отношении кодирования контента) ».

Пример кода:

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! 

1

приведенные выше ответы не работают в моем случае. Вам нужно указать utf-8 в метатеге

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    </head>
    <body>
        <!-- you content goes here -->
    </body>
</html>

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.