Android. WebView et loadData

105

Il est possible d'utiliser la méthode suivante pour le paramétrage du contenu d'une vue Web loadData (String data, String mimeType, String encoding)

Comment gérer le problème avec l'encodage inconnu des données html?!

Existe-t-il une liste d'encodages?!

Je sais de mon université que dans mon cas, le HTML vient de DB et est encodé avec latin-1. J'essaie de définir le paramètre d'encodage sur latin-1, sur ISO-8859-1 / iso-8859-1, mais j'ai toujours des problèmes avec l'affichage de signes spéciaux comme ä, ö, ü.

Je serai très reconnaissant pour tout conseil.

Tima
la source

Réponses:

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

Cela fonctionne parfaitement, en particulier sur Android 4.0, qui ignore apparemment le codage des caractères dans HTML.

Testé sur 2.3 et 4.0.3.

En fait, je n'ai aucune idée de quelles autres valeurs en plus de "base64" le dernier paramètre prend. Certains exemples Google y mettent null.

Patryk
la source
2
Cela ne peut pas fonctionner "parfaitement" si vous avez des caractères en dehors du jeu de caractères US-ASCII.
Andrey Novikov
1
Je viens d'essayer sur un appareil 4.2.2 et fonctionne comme un charme, mais sur un appareil 2.3.6, il montre juste les mêmes caractères d'ordures. : S
Frank
Cela fonctionne également pour moi dans la version 4.1.2 (qui ignore également le jeu de caractères à l'intérieur du HTML), et avec un encodage Latin1! Allez comprendre.
Luis A. Florit
2
@Frank Même ici, testé sur HTC one 2.3.7 (probablement tout en pain d'épice) et j'ai eu la même poubelle, je dois utiliser la solution Andrey Novikov avecWebView.loadDataWithBaseURL()
ForceMagic
Quelle est la différence entre votre réponse et: myWebView.loadData (myHtmlString, "text / html", "UTF-8");
Lou Morda
135

WebView.loadData () ne fonctionne pas du tout correctement. Ce que j'avais à faire était:

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

Je pense que dans votre cas, vous devriez remplacer UTF-8 par latin1 ou ISO-8859-1 à la fois dans l'en-tête et dans WebView.loadData ().

Et, pour donner une réponse complète, voici la liste officielle des encodages: http://www.iana.org/assignments/character-sets

Je mets à jour ma réponse pour être plus inclusive:

Pour utiliser WebView.loadData () avec des encodages non latin1, vous devez encoder le contenu html. L'exemple précédent ne fonctionnait pas correctement sous Android 4+, je l'ai donc modifié pour ressembler à ceci:

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 plus tard, je suis passé à WebView.loadDataWithBaseURL () et le code est devenu très propre et ne dépend pas de la version d'Android:

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

Pour une raison quelconque, ces fonctions ont une implémentation complètement différente.

Andrey Novikov
la source
1
Troène, Andrey. J'ai essayé votre solution. Malheureusement, cela n'a pas fonctionné pour moi :(
Tima
Avez-vous essayé UTF-8 comme je l'ai décrit? Maintenant, quand je pense à votre question, il me vient à l'esprit qu'en Java toutes les chaînes sont en UTF-8, donc mon exemple devrait fonctionner intact.
Andrey Novikov
Toutes les chaînes sont en UTF-8, mais le texte provenant du serveur est en latin-1. Je pense, j'ai essayé avec UTF-8 et avec latin-1 et avec ISO-8859-1, mais j'ai vu encore des signes étranges au lieu de ü, ö, ä. Mais j'ai une autre idée, je vais essayer de convertir le flux d'octets du serveur en chaîne en utilisant le bon encodage. peut-être, ça va m'aider
Tima
4
dans l'encodage 4.0+ devrait être défini dans le type mime aussi "text / html; chartset = utf-8", sinon il ne sera pas reconnu
marwinXXII
2
Le dernier extrait (celui avec loadDataWithBaseURL) fonctionne très bien à la fois sur les appareils 4.2.2 et 2.3.6: D
Frank
36

Si je comprends bien, loadData()génère simplement undata: URL avec les données fournies.

Lisez les javadocs pour loadData():

Si la valeur du paramètre de codage est «base64», les données doivent être codées en base64. Sinon, les données doivent utiliser le codage ASCII pour les octets à l'intérieur de la plage de caractères URL sécurisés et utiliser le codage hexadécimal standard% xx des URL pour les octets en dehors de cette plage. Par exemple, '#', '%', '\', '?' devrait être remplacé par% 23,% 25,% 27,% 3f respectivement.

L'URL du schéma 'data' formée par cette méthode utilise le jeu de caractères US-ASCII par défaut. Si vous avez besoin de définir un jeu de caractères différent, vous devez former une URL de schéma de «données» qui spécifie explicitement un paramètre de jeu de caractères dans la partie mediatype de l'URL et appeler à la place loadUrl (String). Notez que le jeu de caractères obtenu à partir de la partie mediatype d'une URL de données remplace toujours celui spécifié dans le document HTML ou XML lui-même.

Par conséquent, vous devez soit utiliser US-ASCII et échapper vous-même tous les caractères spéciaux, soit simplement encoder tout en utilisant Base64. Ce qui suit devrait fonctionner, en supposant que vous utilisez UTF-8 (je ne l'ai pas testé avec 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
la source
Cela m'a rappelé de vérifier la documentation avant d'errer partout!
Pradeep
Merci d'avoir répondu! Chargeait une aide html contextuelle intégrée différente dans une vue Web, et cela ne fonctionnait que de temps en temps. Cela l'a corrigé.
eric
20

J'ai ce problème, mais:

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

ne fonctionne pas dans tous les appareils. Et je fusionne quelques méthodes:

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

Ça marche.

Aloyan Dmitry
la source
Ce n'est PAS ce que Google recommande. Voir ma réponse et VÉRIFIER la conversation vidéo ;-) stackoverflow.com/questions/3961589/…
Pascal
7

utilisez ceci: String customHtml = text;

           wb.loadDataWithBaseURL(null,customHtml,"text/html", "UTF-8", null);
Krishna
la source
15 post plus tard et c'est le seul qui a fonctionné pour moi
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
la source
5

Le moyen le plus sûr de charger htmlContent dans une vue Web consiste à:

  1. utiliser l'encodage base64 (recommandation officielle)
  2. spécifiez UFT-8 pour le type de contenu html, c'est-à-dire "text / html; charset = utf-8" au lieu de "text / html" (conseil personnel)

"Encodage Base64" est une recommandation officielle qui a été réécrite (déjà présente dans Javadoc) dans le dernier bogue 01/2019 de Chrominium (présent dans WebView M72 (72.0.3626.76)):

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

Déclaration officielle de l'équipe Chromium:

"Solution recommandée:
notre équipe vous recommande d'encoder les données avec Base64. Nous avons fourni des exemples pour savoir comment procéder:

Ce correctif est rétrocompatible (il fonctionne sur les versions antérieures de WebView), et devrait également être à l'épreuve du temps (vous ne rencontrerez pas de futurs problèmes de compatibilité en ce qui concerne l'encodage du contenu). "

Exemple de code:

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
la source
1

les réponses ci-dessus ne fonctionnent pas dans mon cas. Vous devez spécifier utf-8 dans la balise meta

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

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

Celal Kanat
la source