Android. WebView e loadData

104

É possível usar o seguinte método para a configuração do conteúdo de um loadData de visualização da web (String data, String mimeType, String encoding)

Como lidar com o problema de codificação desconhecida de dados html ?!

Existe uma lista de codificações ?!

Eu sei da minha faculdade que, no meu caso, html vem do DB e é codificado com latin-1. Tento definir o parâmetro de codificação para latin-1, para ISO-8859-1 / iso-8859-1, mas ainda tenho problemas com a exibição de sinais especiais como ä, ö, ü.

Ficarei muito grato por qualquer conselho.

Tima
fonte

Respostas:

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

Isso funciona perfeitamente, especialmente no Android 4.0, que aparentemente ignora a codificação de caracteres dentro do HTML.

Testado em 2.3 e 4.0.3.

Na verdade, não tenho ideia sobre quais outros valores além de "base64" o último parâmetro assume. Alguns exemplos do Google colocam null lá.

Patryk
fonte
2
Isso não pode funcionar "perfeitamente" se você tiver caracteres fora do conjunto de caracteres US-ASCII.
Andrey Novikov
1
Tentei em um dispositivo 4.2.2 e funciona perfeitamente, mas em um dispositivo 2.3.6 mostra apenas os mesmos caracteres de lixo. : S
Frank
Isso também funciona para mim no 4.1.2 (que também ignora o conjunto de caracteres dentro do HTML) e com uma codificação Latin1! Vai saber.
Luis A. Florit,
2
@Frank O mesmo aqui, testado no HTC one 2.3.7 (provavelmente todo pão de gengibre) e tenho o mesmo lixo, tenho que usar a solução de Andrey Novikov comWebView.loadDataWithBaseURL()
ForceMagic
Qual é a diferença entre sua resposta e: myWebView.loadData (myHtmlString, "text / html", "UTF-8");
Lou Morda
135

WebView.loadData () não está funcionando corretamente. O que eu tive que fazer foi:

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

Acho que no seu caso você deve substituir UTF-8 por latin1 ou ISO-8859-1 tanto no cabeçalho quanto no WebView.loadData ().

E, para dar uma resposta completa, aqui está a lista oficial de codificações: http://www.iana.org/assignments/character-sets

Eu atualizo minha resposta para ser mais inclusiva:

Para usar WebView.loadData () com codificações não latin1, você deve codificar o conteúdo html. O exemplo anterior não estava funcionando corretamente no Android 4+, então eu o modifiquei para ter a seguinte aparência:

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

}

Mais tarde, porém, mudei para WebView.loadDataWithBaseURL () e o código tornou-se muito limpo e não depende da versão do Android:

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

Por alguma razão, essas funções têm implementações completamente diferentes.

Andrey Novikov
fonte
1
Alfeneiro, Andrey. Tentei sua solução. Infelizmente não funcionou para mim :(
Tima
Você experimentou o UTF-8 conforme descrevi? Agora, quando penso em sua pergunta, me ocorre que em Java todas as strings estão em UTF-8, então meu exemplo deve funcionar intacto.
Andrey Novikov
Todas as Strings são UTF-8, mas o texto que vem do servidor está em latin-1. Acho que tentei com UTF-8 e com latin-1 e com ISO-8859-1, mas ainda vi sinais estranhos em vez de ü, ö, ä. Mas tenho outra ideia, tentarei converter o fluxo de bytes do servidor em string usando a codificação correta. talvez isso me ajude
Tima
4
em 4.0+ a codificação deve ser definida no tipo MIME também "text / html; chartset = utf-8", caso contrário, não será reconhecido
marwinXXII
2
O último snippet (aquele com loadDataWithBaseURL) funciona muito bem em dispositivos 4.2.2 e 2.3.6: D
Frank
36

Pelo que entendi, loadData()simplesmente gera um data:URL com os dados fornecidos.

Leia os javadocs para loadData():

Se o valor do parâmetro de codificação for 'base64', os dados devem ser codificados como base64. Caso contrário, os dados devem usar codificação ASCII para octetos dentro do intervalo de caracteres de URL seguros e usar a codificação hexadecimal% xx padrão de URLs para octetos fora desse intervalo. Por exemplo, '#', '%', '\', '?' deve ser substituído por% 23,% 25,% 27,% 3f respectivamente.

O URL de esquema de 'dados' formado por este método usa o conjunto de caracteres US-ASCII padrão. Se você precisar definir um conjunto de caracteres diferente, deve formar um URL de esquema de 'dados' que especifica explicitamente um parâmetro de conjunto de caracteres na parte mediatype do URL e chamar loadUrl (String). Observe que o conjunto de caracteres obtido da parte do tipo de mídia de um URL de dados sempre substitui o especificado no próprio documento HTML ou XML.

Portanto, você deve usar US-ASCII e escapar quaisquer caracteres especiais você mesmo ou apenas codificar tudo usando Base64. O seguinte deve funcionar, supondo que você use UTF-8 (não testei isso com o 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
fonte
Isso me lembrou de verificar a documentação antes de vagar por toda parte!
Pradeep
Obrigado pela resposta! Estava carregando diferente ajuda HTML contextual embutida em um webview, e só funcionava algumas vezes. Isso corrigiu o problema.
Eric
20

Eu tenho esse problema, mas:

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

não funciona em todos os dispositivos. E eu mesclo alguns métodos:

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

Funciona.

Aloyan Dmitry
fonte
Isso NÃO é o que o Google recomenda. Veja minha resposta e VERIFIQUE a conversa de vídeo ;-) stackoverflow.com/questions/3961589/…
Pascal
7

use isto: String customHtml = text;

           wb.loadDataWithBaseURL(null,customHtml,"text/html", "UTF-8", null);
Krishna
fonte
15 post depois e este é o único que funcionou para mim
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
fonte
5

A maneira mais segura de carregar htmlContent em uma visualização da Web é:

  1. usar codificação base64 (recomendação oficial)
  2. especifique UFT-8 para o tipo de conteúdo html, ou seja, "text / html; charset = utf-8" em vez de "text / html" (conselho pessoal)

"Codificação Base64" é uma recomendação oficial que foi escrita novamente (já presente no Javadoc) no último bug 01/2019 no Chrominium (presente no WebView M72 (72.0.3626.76)):

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

Declaração oficial da equipe do Chromium:

"Correção recomendada:
nossa equipe recomenda que você codifique os dados com Base64. Fornecemos exemplos de como fazer isso:

Esta correção é compatível com versões anteriores (funciona em versões anteriores do WebView) e também deve ser preparada para o futuro (você não terá problemas de compatibilidade futuros com relação à codificação de conteúdo). "

Amostra de código:

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
fonte
1

as respostas acima não funcionam no meu caso. Você precisa especificar utf-8 na metatag

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

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

Celal Kanat
fonte