Giới thiệu
Hướng dẫn này trình bày cách thiết lập encoding văn bản mặc định (default text encoding) cho Android WebView để hiển thị đúng tiếng Việt và các ký tự Unicode khi server không gửi header charset.
Các bước thực hiện
Bước 1: Tạo dự án mới
Tạo dự án Android Studio: File → New Project.
Bước 2: Layout activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<WebView
android:id="@+id/web_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Bước 3: MainActivity.java
package com.example.myapplication;
import android.os.Build;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.app.ProgressDialog;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Đang tải dữ liệu...");
progressDialog.setCancelable(false);
WebView webView = findViewById(R.id.web_view);
webView.requestFocus();
WebSettings webSettings = webView.getSettings();
// QUAN TRỌNG: Thiết lập encoding mặc định UTF-8
webSettings.setDefaultTextEncodingName("utf-8");
webSettings.setJavaScriptEnabled(true);
webSettings.setBuiltInZoomControls(true);
webSettings.setDisplayZoomControls(false);
webSettings.setLoadWithOverviewMode(true);
webSettings.setUseWideViewPort(true);
webView.loadUrl("https://touch.facebook.com/");
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
progressDialog.dismiss();
}
});
webView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int newProgress) {
if (newProgress < 100) {
progressDialog.show();
}
if (newProgress == 100) {
progressDialog.dismiss();
}
}
});
}
}
Bước 4: AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="com.example.myapplication">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
Giải thích setDefaultTextEncodingName
Khi nào cần thiết?
- Server không gửi header
Content-Type: text/html; charset=utf-8. - Server gửi header charset sai (ví dụ: ISO-8859-1 cho trang tiếng Việt).
- File HTML local (file://) không có meta charset.
- Trang web cũ không tuân thủ chuẩn HTML5.
Cơ chế ưu tiên xác định encoding
- HTTP Header Content-Type charset (cao nhất) - Server gửi.
- HTML Meta Charset -
<meta charset="utf-8">hoặc<meta http-equiv="Content-Type" content="text/html; charset=utf-8">. - setDefaultTextEncodingName() - Fallback cuối cùng của WebView.
- Auto-detection - WebView tự đoán (ít tin cậy).
Các encoding thường gặp
| Encoding | Tên gọi | Sử dụng cho |
|---|---|---|
| utf-8 | Unicode UTF-8 | Tất cả ngôn ngữ (khuyến nghị) |
| iso-8859-1 | Latin-1 | Tây Âu (không hỗ trợ tiếng Việt) |
| windows-1252 | CP1252 | Windows Western European |
| windows-1258 | CP1258 | Tiếng Việt (legacy, cũ) |
| gb2312 / gbk | Chinese Simplified | Trung Quốc |
| big5 | Chinese Traditional | Taiwan, HK |
| shift_jis | Japanese | Nhật Bản |
| euc-kr | Korean | Hàn Quốc |
Best Practices cho tiếng Việt
WebSettings settings = webView.getSettings();
// 1. Luôn set UTF-8 làm fallback
settings.setDefaultTextEncodingName("utf-8");
// 2. Đảm bảo JavaScript bật (nhiều trang web hiện đại cần JS để render đúng)
settings.setJavaScriptEnabled(true);
// 3. Cho phép zoom để user tự điều chỉnh font
settings.setBuiltInZoomControls(true);
settings.setDisplayZoomControls(false);
// 4. Viewport settings cho responsive
settings.setLoadWithOverviewMode(true);
settings.setUseWideViewPort(true);
settings.setSupportZoom(true);
// 5. Cache settings
settings.setCacheMode(WebSettings.LOAD_DEFAULT);
settings.setAppCacheEnabled(true);
// 6. Mixed content (nếu cần load HTTP trong HTTPS)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
settings.setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
}
Test encoding
Tạo file HTML test local (assets/test_encoding.html):
<!DOCTYPE html>
<html>
<head>
<!-- KÔNG CÓ META CHARSET -->
<title>Test Encoding</title>
</head>
<body>
<h1>Tiếng Việt: ÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚÝĐàáâãèéêìíòóôõùúýđ</h1>
<p>Nếu thấy chữ Việt bình thường => UTF-8 hoạt động</p>
<p>Nếu thấy ký tự lạ => Encoding sai</p>
</body>
</html>
Load trong WebView: webView.loadUrl("file:///android_asset/test_encoding.html");
Lưu ý
- setDefaultTextEncodingName chỉ là fallback - header server và meta tag ưu tiên hơn.
- Không thể ép buộc override encoding nếu server đã gửi header charset rõ ràng.
- Luôn khuyến khích backend set header
Content-Type: text/html; charset=utf-8đúng chuẩn.