Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách thiết lập encoding văn bản mặc định cho WebView Android

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

  1. HTTP Header Content-Type charset (cao nhất) - Server gửi.
  2. HTML Meta Charset - <meta charset="utf-8"> hoặc <meta http-equiv="Content-Type" content="text/html; charset=utf-8">.
  3. setDefaultTextEncodingName() - Fallback cuối cùng của WebView.
  4. Auto-detection - WebView tự đoán (ít tin cậy).

Các encoding thường gặp

EncodingTên gọiSử dụng cho
utf-8Unicode UTF-8Tất cả ngôn ngữ (khuyến nghị)
iso-8859-1Latin-1Tây Âu (không hỗ trợ tiếng Việt)
windows-1252CP1252Windows Western European
windows-1258CP1258Tiếng Việt (legacy, cũ)
gb2312 / gbkChinese SimplifiedTrung Quốc
big5Chinese TraditionalTaiwan, HK
shift_jisJapaneseNhật Bản
euc-krKoreanHà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.