Reading Time: 7 minutes

WebView trong Android là một thành phần cho phép lập trình viên nhúng nội dung web trực tiếp vào ứng dụng của mình. Với công cụ mạnh mẽ này, ta có thể tích hợp các trang HTML vào giao diện của các chương trình Android một cách đơn giản.

webview trong android

WebView trong Android

Component WebView là một trình duyệt hoàn chỉnh được triển khai dưới dạng một lớp con (subclass) của View để nhúng vào ứng dụng Android.

Vai trò quan trọng của WebView

Với mã HTML có phạm vi giới hạn, ta có thể sử dụng phương thức static fromHtml() từ class tiện ích Html để phân tích chuỗi HTML và hiển thị trong một TextView. TextView có thể render các định dạng đơn giản như kiểu chữ (in đậm, in nghiêng), font chữ (serif, sans-serif), màu sắc, liên kết, v.v. Tuy nhiên, khi phải xử lý các định dạng phức tạp hoặc nội dung HTML lớn, TextView không đáp ứng tốt.

Ví dụ, ta không thể duyệt Facebook bằng TextView. Trong những trường hợp như vậy, WebView là widget phù hợp hơn vì nó có thể xử lý nhiều loại thẻ HTML hơn. WebView còn có thể xử lý cả CSS và JavaScript, những thứ mà TextView bỏ qua.

WebView cũng hỗ trợ các tính năng duyệt web quen thuộc như lưu lại lịch sử các trang đã truy cập để điều hướng tới-lui. Dù vậy, WebView cũng có nhược điểm. Dùng widget này tốn nhiều tài nguyên bộ nhớ hơn so với TextView. Lý do là vì WebView sử dụng WebKit/Blink, engine mã nguồn mở được dùng để render nội dung web trên các trình duyệt như Chrome.

Ví dụ sử dụng WebView

Component WebView được khai báo trong file layout XML tại nơi mà ta muốn nó hiển thị. Trong ví dụ này, ta sẽ chèn nó vào file activity_main.xml như minh họa bên dưới:

<RelativeLayout xmlns:android="<https://schemas.android.com/apk/res/android>"
    xmlns:tools="<https://schemas.android.com/tools>" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <WebView
        android:id="@+id/webview"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</RelativeLayout>

Code cho WebView trong Android Studio

Component WebView được khởi tạo trong Activity bằng id đã được định nghĩa trong file layout như trong dòng code dưới đây:

WebView webView = (WebView) findViewById(R.id.webview);

Phương thức loadUrl trong WebView

Sau khi có được tham chiếu tới WebView, ta có thể cấu hình và tải nội dụng từ URL thông qua HTTP. Dòng code sau dùng phương thức loadUrl() được dùng để tải URL vào WebView:

webView.loadUrl("<https://www.journaldev.com>");

Có hai điểm quan trọng mà ta cần chú ý:

  1. Kích hoạt JavaScript: Mặc định, JavaScript bị tắt trong WebView. Do đó, các trang web chứa mã JavaScript sẽ không thể hoạt động bình thường. Để kích hoạt JavaScript, ta cần thêm đoạn code sau trên instance của WebView:
getSettings().setJavaScriptEnabled(true);
  1. Thêm quyền truy cập Internet: Để WebView có thể tìm và tải nội dung các URL, ta cần cấp quyền truy cập internet cho ứng dụng. Dòng code sau cần được thêm vào file AndroidManifest.xml, bên trên thẻ <application>:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="<https://schemas.android.com/apk/res/android>"
    package="com.journaldev.webview" >

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Class MainActivity dưới đây bao gồm tất cả các tính năng đã được đề cập từ đầu đến giờ.

package com.journaldev.webview;

import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebSettings;
import android.webkit.WebView;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        WebView webView = (WebView) findViewById(R.id.webview);

        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);

        webView.loadUrl("<https://www.journaldev.com>");
    }

}

Thiết lập WebViewClient

Hành vi mặc định của hệ thống khi người dùng nhấn vào một liên kết bên trong trang web là sẽ mở ứng dụng trình duyệt mặc định. Điều này có thể làm gián đoạn trải nghiệm của người dùng trong ứng dụng.

Để giữ cho việc điều hướng diễn ra bên trong WebView (và bên trong ứng dụng), ta cần tạo một subclass của WebViewClient và ghi đè phương thức shouldOverrideUrlLoading() của nó. Dưới đây là ví dụ về một subclass của WebViewClient:

private class MyWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView webView, String url) {
        return false;
    }
}

Khi phương thức shouldOverrideUrlLoading() trả về false, URL được truyền vào sẽ được tải bên trong WebView thay vì trong trình duyệt như thông thường.

Để phân biệt và xử lý các URL khác nhau (URL nào tải trong ứng dụng, URL nào mở bằng trình duyệt), ta cần thêm đoạn code sau vào phương thức shouldOverrideUrlLoading():

if(url.indexOf("journaldev.com") > -1 ) return false;
        return true;

Lưu ý: Việc trả về true không có nghĩa là URL sẽ được mở trong ứng dụng trình duyệt. Thậm chí, URL đó sẽ không được mở. Để tải URL trong trình duyệt, ta cần phải kích hoạt một Intent (đối tượng dùng để yêu cầu một hành động từ một thành phần ứng dụng khác). Subclass dưới đây bao gồm tất cả các cấu hình chúng ta đã thêm vào.

package com.journaldev.webview;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class WebViewClientImpl extends WebViewClient {

    private Activity activity = null;

    public WebViewClientImpl(Activity activity) {
        this.activity = activity;
    }

    @Override
    public boolean shouldOverrideUrlLoading(WebView webView, String url) {
        if(url.indexOf("journaldev.com") > -1 ) return false;

        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        activity.startActivity(intent);
        return true;
    }

}

Constructor của class này nhận vào một Activity làm tham số để có thể kích hoạt Intent mở trình duyệt. Trước khi khởi tạo subclass này trong MainActivity, hãy cùng xem qua các năng quan trọng khác.

Điều hướng WebView bằng nút Back/Trở về

Khi nhấn nút Back trong ứng dụng hiện tại, ta sẽ thấy ứng dụng thoát ra màn hình chính, ngay cả khi chúng ta đã mở một số trang bên trong WebView. Để có thể quay lại các trang đã xem trong lịch sử duyệt web của WebView khi nhấn nút Back, ta cần sửa đổi lại chức năng của nút này như trong đoạn code dưới đây:

@Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK) && this.webView.canGoBack()) {
            this.webView.goBack();
            return true;
        }

        return super.onKeyDown(keyCode, event);
    }

Phương thức onKeyDown() đã được ghi đè. Bây giờ nó sẽ kiểm tra xem WebView có thể quay lại trang trước hay không. Nếu người dùng đã rời khỏi trang đầu tiên được mở trong WebView, thì WebView có thể quay lại trang đó.

WebView duy trì một lịch sử duyệt web giống như một trình duyệt thông thường. Nếu không còn trang nào trong lịch sử, hành vi mặc định của nút Back sẽ được thực thi (tức là thoát ứng dụng). Dưới đây là code hoàn chỉnh cho MainActivity với các tính năng trên đã được thêm vào.

package com.journaldev.webview;

import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.webkit.WebSettings;
import android.webkit.WebView;

public class MainActivity extends Activity {

    private WebView webView = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        this.webView = (WebView) findViewById(R.id.webview);

        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);

        WebViewClientImpl webViewClient = new WebViewClientImpl(this);
        webView.setWebViewClient(webViewClient);

        webView.loadUrl("<https://www.journaldev.com>");
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK) && this.webView.canGoBack()) {
            this.webView.goBack();
            return true;
        }

        return super.onKeyDown(keyCode, event);
    }

}

Hình ảnh bên dưới cho thấy giao diện và hoạt động của ứng dụng ví dụ trên. Ta có thể thấy WebView đã tải thành công URL được chỉ định sẵn.

Ứng dụng ví dụ sử dụng Webview trong Android

Các phương pháp thay thế để tải nội dung vào WebView

Từ đầu đến giờ, chúng ta chỉ sử dụng phương thức loadUrl() để tải nội dung vào WebView. Trong phần này, ta sẽ tìm hiểu các cách khác để tải nội dung, nhưng trước hết hãy điểm qua nhanh các trường hợp sử dụng của loadUrl().

loadUrl() hoạt động với:

  • Các URL http:// và https://
  • Các URL file:// trỏ đến hệ thống tệp cục bộ
  • Các URL file:///android_asset/ trỏ đến một trong các asset của ứng dụng
  • Các URL content:// trỏ đến một ContentProvider đang cung cấp nội dung có thể stream

Thay vì dùng loadUrl(), ta có thể sử dụng loadData() để hiển thị các đoạn code hoặc toàn bộ mã HTML. Có hai biến thể của loadData(). Biến thể đơn giản hơn cho phép ta cung cấp nội dung, kiểu MIME và bảng mã (encoding), tất cả đều ở dạng chuỗi. Thông thường, kiểu MIME sẽ là text/html và bảng mã là UTF-8 cho nội dung HTML thông thường, như ví dụ dưới đây:

webView.loadData("<html><body>Hello, world!</body></html>",
                  "text/html", "UTF-8");

Dưới đây là kết quả khi code trên được thêm vào MainActivity:

package com.journaldev.webview;

import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.webkit.WebSettings;
import android.webkit.WebView;

public class MainActivity extends Activity {

    private WebView webView = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        this.webView = (WebView) findViewById(R.id.webview);

        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);

        WebViewClientImpl webViewClient = new WebViewClientImpl(this);
        webView.setWebViewClient(webViewClient);

        //webView.loadUrl("<https://www.journaldev.com>");
        webView.loadData("<html><body>Hello, world!</body></html>", "text/html", "UTF-8");
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK) && this.webView.canGoBack()) {
            this.webView.goBack();
            return true;
        }

        return super.onKeyDown(keyCode, event);
    }

}

Ví dụ sử dụng loadUrl()

Ngoài ra còn có phương thức loadDataWithBaseURL(). Phương thức này nhận vào một URL cơ sở (base URL) được dùng để xử lý các URL tương đối trong mã HTML.

Bất kỳ URL tương đối nào (ví dụ: <img src=“images/sample.png”>) sẽ được hiểu là đường dẫn tương đối so với URL cơ sở đã cung cấp cho loadDataWithBaseURL(). Tham số historyUrl là URL sẽ được ghi vào lịch sử duyệt web nội bộ trong WebView cho nội dung HTML vừa được tải. Đoạn mã sau đây minh họa cú pháp của phương thức này:

String baseUrl    = "<https://www.journaldev.com>";
String data       = "Relative Link";
String mimeType   = "text/html";
String encoding   = "UTF-8";
String historyUrl = "<https://www.journaldev.com>";

webView.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);

Bài hướng dẫn về sử dụng Android WebView đến đây là kết thúc. Để củng cố kiến thức và tự mình thử nghiệm trực tiếp, bạn có thể tải project ví dụ trên từ link này và bắt đầu thực hành nhúng nội dung web vào ứng dụng Android của riêng mình.

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.

Đăng ký nhận Newsletter

Nhận các nội dung hữu ích mới nhất