Android WebView显示UTF-8字符乱码问题。

78

我在我的安卓应用中使用了一些WebView,但是无法使它们以utf-8编码显示。

如果使用这个,我将看不到我的斯堪的纳维亚字符:

mWebView.loadUrl("file:///android_asset/om.html")

如果我尝试这个,就什么都不会显示

mWebView.loadDataWithBaseURL("file:///android_asset/om.html", null, "text/html", "utf-8",null);

敬礼


1
虽然这是 android-webview-utf-8-not-showing 的一个副本,但从2010年开始的已接受的解决方案在较新的Android版本中不起作用。@Cameron Lowell Palmer 和 @R Earle Harris 的答案包含适用于新版 Android 的信息。 - k3b
确切地说,它是相似的,但不是重复的,这代表了一个更强大的一般性问题和答案。请投票重新开放。 - Cameron Lowell Palmer
Elena说,你关闭这个问题似乎有些自私。这里的答案得分比你的答案高,正是因为问题足够不同,答案更强大。 - Cameron Lowell Palmer
这是一个重复的问题:https://dev59.com/tXA75IYBdhLWcg3waIMJ - Jorgesys
@Elenasys 不同意。它们相似,但存在足够的差异。 - Cameron Lowell Palmer
9个回答

158
您可以尝试在加载数据之前编辑您的 webview 设置:
WebSettings settings = mWebView.getSettings();
settings.setDefaultTextEncodingName("utf-8");

另外,如下方评论所提供的,确保在loadData调用中添加"charset=utf-8"

mWebView.loadData(getString(R.string.info_texto), "text/html; charset=utf-8", "utf-8");

1
这个方法不会像我回答的那样工作。问题在于该方法存在一个错误,而且仅指定UTF-8编码是不够的。 - Cameron Lowell Palmer
2
这适用于Android 2.2,但要使其在Android 4.04上正常工作,您需要使用Cameron建议的loadDataWithBaseURL()方法(https://dev59.com/-G445IYBdhLWcg3wTIfm#10831462)。 - sulai
43
这对我来说在Android 2.2.1、4.0.4和4.1.2上都有效。您还需要在loadData调用中添加"charset=utf-8"。像这样:webview.loadData(getString(R.string.info_texto), "text/html; charset=utf-8", "utf-8"); - Derzu

135

似乎一直存在某种形式的问题。

问题1733

使用loadDataWithBaseURL代替loadData。

// Pretend this is an html document with those three characters
String scandinavianCharacters = "øæå";

// Won't render correctly
webView.loadData(scandinavianCharacters, "text/html", "UTF-8");

// Will render correctly
webView.loadDataWithBaseURL(null, scandinavianCharacters, "text/html", "UTF-8", null);

现在最令人讨厌的部分是,在三星Galaxy S II(4.0.3)上,loadData()运行得很好,但在Galaxy Nexus(4.0.2)上测试时,多字节字符会乱码,除非您使用loadDataWithBaseURL()。 WebView文档

Android的最新版本

一些用户报告称loadData调用的行为发生了变化,需要将mimeType包括charset=utf-8

webView.loadData(scandinavianCharacters, "text/html; charset=utf-8", "UTF-8");

您也可以使用这个公式与WebSettings一起使用。

WebView webView = (WebView) findViewById(R.id.DemoWebView);
WebSettings webSettings = webView.getSettings();
webSettings.setDefaultTextEncodingName("utf-8");  
webView.loadData(scandinavianCharacters, "text/html; charset=utf-8", null);

令人惊讶的是,Android仍然没有解决这个基本问题。


1
谢谢这个。对我很有效。 - Sean Glover
1
谢谢,我的Galaxy S3上可以正常工作。不过这很烦人。 - nspo
@CassioLandim 你需要提供更多的细节。 - Cameron Lowell Palmer
2
我正在使用Android 4.4.4,但它对我无效。text/html; charset=utf-8有效。 - Azad
1
能够得到一个明确的答案,告诉我们这个API级别的改变是什么,那就太好了。在三星Galaxy S3(API 16)上测试时,“text/html; charset=utf-8”会导致乱码,而“text/html”则正常。在Moto G(API 23)上则相反。我已经采用了if(Build.VERSION.SDK_INT>16)来选择编码字符串,但我担心这仍然不能适用于所有设备/API级别。 - QuantumTiger
显示剩余2条评论

27

德尔祖的建议非常有帮助:

webview.loadData(getString(R.string.info_texto), "text/html; charset=utf-8", "utf-8");

我在Android 2.x上使用了UTF-8,而在4.x上出现了乱码的ANSI,直到我安装了

 charset=utf-8

wv.loadUrlWhatever()的调用中。Derzu非常注重细节。


不需要额外设置,Eric Nordvik在https://dev59.com/-G445IYBdhLWcg3wTIfm#4933345中描述的设置甚至都不需要。至少对于4.1.2版本来说是这样。 - John
太好了:节省了我的时间。 - Dhruvil Patel

12

通过 HTTP 服务器提供 HTML 页面时,有两种方式可以指定内容编码。通常,服务器会在 HTTP 标头中指定内容编码,但由于该页面是从文件加载的,所以没有 HTTP 事务,因此也没有标头。因此,WebView 假定默认编码为 Latin-1。

但是,您可以使用 <meta> 标签指定内容编码。构建 html 文件的方式如下:

<!DOCTYPE HTML>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title>Title</title>
</head>
Your content following

然后使用mWebView.loadUrl("file:///android_asset/om.html");将其加载到 WebView 中。它应该会像您期望的那样显示非拉丁字符。


2
这个解决方案正是我所需要的,因为我通过文件加载HTML内容。谢谢:D - Agung Pratama

9
WebView wv = (WebView) findViewById(R.id.rowWebview);
WebSettings settings = wv.getSettings();
settings.setDefaultTextEncodingName("utf-8");                   
wv.loadData(topHtml, "text/html; charset=utf-8",null);

这两者的组合对我来说似乎很有效。由于某种原因,它喜欢在mime类型中使用null作为编码和字符集:/ 很奇怪。这解决了数月的烦恼。


是的,只有这两个“utf-8”的设置也帮助了我。 meta标签<meta http-equiv="content-type" content="text/html; charset=UTF-8">在我使用loadUrl时有所帮助,但在使用loadData时被忽略(在API 16 + 21上进行测试)。 - Dirk

2
你需要交换你的前两个参数。请查看此线程:Android WebView UTF-8 not showing 所以你的代码应该像这样:
mWebView.loadDataWithBaseURL(null, "file:///android_asset/om.html", "text/html", "utf-8",null);

2
根据文档,正确的顺序是:public void loadDataWithBaseURL(String baseUrl,String data,String mimeType,String encoding,String historyUrl) - Cameron Lowell Palmer
是的,文档是正确的。我的答案已经考虑到了这一点。基本URL需要为空。 - Sparky
你的负载是带有 file:// 的字符串,这让我很困惑。 - Cameron Lowell Palmer

1

为了始终显示正确的内容,应牢记以下3点:

  1. 使用loadDataWithBaseUrl而不是loadData函数。
  2. 在html文件中设置正确的编码作为meta标签。
  3. 在WebSettings中设置defaultTextEncodingName。

示例已经通过其他答案提供,我就不再重复了!


你讲解了如何查看包含utf-8的内容,但是如何分享包含utf-8的url呢?比如这个链接(我想在我的应用程序中与社交网络分享URL):http://yazd20.com//News/2015/11/استند-آب-كمدي-حسن-ريوندي-در-يزد.html - Ahmad Ebrahimi

0
mwebView.loadData(URLEncoder.encode(data, "utf-8").replaceAll("\\+"," "), "text/html", "utf-8");

0

我不确定在加载该页面之前你在做什么。这个安全性改变是否与此有关?你是从网页加载页面吗?

针对1.0版本的注意事项。由于WebKit的更改,通过“file:///android_asset/”访问子资源的资产文件的访问权限更受限制。如果您提供null或空字符串作为baseUrl,则无法访问资产文件。如果baseUrl不是http(s)/ ftp(s)/ about / javascript作为方案的任何其他内容,则可以访问子资源的资产文件。

引用自此处:http://developer.android.com/reference/android/webkit/WebView.html 在“loadDataWithBaseURL”方法的部分中。

你能否使用“loadData”进行快速测试?指定“utf-8”编码并将斯堪的纳维亚字符粘贴到数据参数中。这是一个简单的测试,可消除安全问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接