Android. WebView và loadData


104

Có thể sử dụng phương pháp sau để cài đặt loadData của chế độ xem web (Dữ liệu chuỗi, Kiểu mimeType, Mã hóa chuỗi)

Làm thế nào để xử lý vấn đề với mã hóa dữ liệu html không xác định?!

Có một danh sách các mã hóa ?!

Tôi biết từ trường đại học của tôi rằng trong trường hợp của tôi html đến từ DB và được mã hóa bằng latin-1. Tôi cố gắng đặt tham số mã hóa thành latin-1, thành ISO-8859-1 / iso-8859-1, nhưng vẫn gặp sự cố khi hiển thị các dấu hiệu đặc biệt như ä, ö, ü.

Tôi sẽ rất cảm ơn vì bất kỳ lời khuyên nào.

Câu trả lời:


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

Điều này hoạt động hoàn hảo, đặc biệt là trên Android 4.0, dường như bỏ qua mã hóa ký tự bên trong HTML.

Đã thử nghiệm trên 2.3 và 4.0.3.

Trên thực tế, tôi không biết giá trị nào khác ngoài "base64" mà tham số cuối cùng nhận. Một số ví dụ của Google đặt null ở đó.


2
Điều này không thể hoạt động "hoàn hảo" nếu bạn có các ký tự bên ngoài bộ mã US-ASCII.
Andrey Novikov

1
Chỉ cần thử trên thiết bị 4.2.2 và hoạt động giống như một sự quyến rũ, nhưng trên thiết bị 2.3.6, nó chỉ hiển thị các ký tự rác giống nhau. : S
Frank

Điều này cũng hoạt động đối với tôi trong 4.1.2 (người cũng bỏ qua bộ ký tự bên trong HTML) và với mã hóa Latin1! Đi tìm hình.
Luis A. Florit

2
@Frank Cùng ở đây, thử nghiệm trên HTC One 2.3.7 (có thể là tất cả các bánh gừng) và có thùng rác cùng, tôi đã sử dụng giải pháp Andrey Novikov vớiWebView.loadDataWithBaseURL()
ForceMagic

Sự khác biệt giữa câu trả lời của bạn và: myWebView.loadData (myHtmlString, "text / html", "UTF-8");
Lou Morda

135

WebView.loadData () không hoạt động bình thường. Những gì tôi phải làm là:

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

Tôi nghĩ trong trường hợp của bạn, bạn nên thay thế UTF-8 bằng latin1 hoặc ISO-8859-1 cả trong tiêu đề và trong WebView.loadData ().

Và, để đưa ra câu trả lời đầy đủ, đây là danh sách chính thức của các bảng mã: http://www.iana.org/assignments/character-sets

Tôi cập nhật câu trả lời của mình để bao hàm hơn:

Để sử dụng WebView.loadData () với các mã hóa không phải latin1, bạn phải mã hóa nội dung html. Ví dụ trước đó không hoạt động chính xác trong Android 4+, vì vậy tôi đã sửa đổi nó để trông như sau:

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

}

Nhưng sau đó tôi đã chuyển sang WebView.loadDataWithBaseURL () và mã trở nên rất sạch và không phụ thuộc vào phiên bản Android:

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

Vì một số lý do mà các chức năng này có cách thực hiện hoàn toàn khác nhau.


1
Privet, Andrey. Tôi đã thử giải pháp của bạn. Thật không may, nó không hoạt động với tôi :(
Tima

Bạn đã thử UTF-8 như tôi mô tả chưa? Bây giờ khi tôi nghĩ về câu hỏi của bạn, tôi thấy rằng trong Java tất cả các chuỗi đều ở dạng UTF-8, vì vậy ví dụ của tôi sẽ hoạt động nguyên vẹn.
Andrey Novikov

Tất cả các Chuỗi là UTF-8, nhưng văn bản đến từ máy chủ là bằng tiếng latin-1. Tôi nghĩ, tôi đã thử với UTF-8, latin-1 và ISO-8859-1, nhưng vẫn thấy các dấu hiệu lạ thay vì ü, ö, ä. Nhưng tôi có một ý tưởng khác, tôi sẽ cố gắng chuyển đổi luồng byte từ máy chủ thành chuỗi bằng cách sử dụng mã hóa bên phải. có lẽ, điều đó sẽ giúp tôi
Tima

4
trong 4.0 + mã hóa nên được đặt trong kịch câm gõ quá "text / html; chartset = utf-8", nếu không nó sẽ không được công nhận
marwinXXII

2
Đoạn mã cuối cùng (đoạn mã có loadDataWithBaseURL) hoạt động tốt trên cả thiết bị 4.2.2 và 2.3.6: D
Frank

36

Theo tôi hiểu, loadData()chỉ cần tạo một data:URL với dữ liệu được cung cấp.

Đọc javadocs cho loadData():

Nếu giá trị của tham số mã hóa là 'base64', thì dữ liệu phải được mã hóa dưới dạng base64. Nếu không, dữ liệu phải sử dụng mã hóa ASCII cho các octet bên trong phạm vi ký tự URL an toàn và sử dụng mã hóa hex% xx tiêu chuẩn của URL cho các octet bên ngoài phạm vi đó. Ví dụ, '#', '%', '\', '?' nên được thay thế bằng% 23,% 25,% 27,% 3f tương ứng.

URL lược đồ 'dữ liệu' được hình thành bằng phương pháp này sử dụng bộ mã US-ASCII mặc định. Nếu bạn cần đặt một bộ ký tự khác, bạn nên tạo một URL lược đồ 'dữ liệu' chỉ định rõ ràng một thông số bộ ký tự trong phần loại trung gian của URL và thay vào đó hãy gọi loadUrl (Chuỗi). Lưu ý rằng bộ ký tự thu được từ phần loại trung gian của URL dữ liệu luôn ghi đè được chỉ định trong chính tài liệu HTML hoặc XML.

Do đó, bạn nên sử dụng US-ASCII và tự mình thoát khỏi bất kỳ ký tự đặc biệt nào hoặc chỉ mã hóa mọi thứ bằng Base64. Điều sau sẽ hoạt động, giả sử bạn sử dụng UTF-8 (tôi chưa thử nghiệm điều này với 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");

Điều này nhắc nhở tôi kiểm tra tài liệu trước khi lang thang khắp nơi!
Pradeep

Cảm ơn vì câu trả lời! Đang tải các trợ giúp html khác nhau được xây dựng theo ngữ cảnh trong một webview và nó chỉ hoạt động đôi khi. Điều này đã sửa chữa nó.
eric,

20

Tôi có vấn đề này, nhưng:

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

không hoạt động trong tất cả các thiết bị. Và tôi hợp nhất một số phương pháp:

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

Nó hoạt động.


Đây KHÔNG phải là những gì Google khuyến nghị. Xem câu trả lời của tôi và KIỂM TRA cuộc trò chuyện qua video ;-) stackoverflow.com/questions/3961589/…
Pascal

6

sử dụng cái này: String customHtml = text;

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

15 bài sau và đây là bài duy nhất phù hợp với tôi
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);

5

Cách an toàn nhất để tải htmlContent trong chế độ xem Web là:

  1. sử dụng mã hóa base64 (khuyến nghị chính thức)
  2. chỉ định UFT-8 cho loại nội dung html, tức là "text / html; charset = utf-8" thay vì "text / html" (lời khuyên cá nhân)

"Mã hóa Base64" là khuyến nghị chính thức đã được viết lại (đã có trong Javadoc) trong lỗi mới nhất vào tháng 1/2019 trong Chrominium (có trong WebView M72 (72.0.3626.76)):

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

Tuyên bố chính thức từ nhóm Chromium:

"Cách khắc phục được đề xuất:
Nhóm của chúng tôi khuyên bạn nên mã hóa dữ liệu bằng Base64. Chúng tôi đã cung cấp các ví dụ về cách làm như vậy:

Bản sửa lỗi này tương thích ngược (nó hoạt động trên các phiên bản WebView trước đó) và cũng phải phù hợp với tương lai (bạn sẽ không gặp phải các vấn đề tương thích trong tương lai đối với mã hóa nội dung). "

Mẫu mã:

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

các câu trả lời trên không hoạt động trong trường hợp của tôi. Bạn cần chỉ định utf-8 trong thẻ meta

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

-1

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.