1 số hạn chế ở khi sử dụng WebView
Khai báo quyền truy cập internet trong file AndroidManifest.xml.
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
package com.eitguide.demowebview; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.webkit.WebView; public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private static final String EITGUIDE_URL = "https://eitguide.net/"; private WebView webView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView = (WebView)findViewById(R.id.webview); webView.getSettings().setJavaScriptEnabled(true); webView.loadUrl(EITGUIDE_URL); } }
Khi chạy đoạn code trên thì không thấy xuất hiện vấn đề, tuy nhiên khi nhấn vào 1 đường dẫn trên web được nạp bởi WebView
thì trang web này được mở bởi trình duyệt web mặc định trên Android chứ không phải là WebView
. Điều này không là điều không mong đợi, tất cả sự kiện nên xử lý với WebView
chứ không phải là sử dụng trình duyệt web mặc định.
Để khắc phục điều này có thể sử dụng WebViewClient
.
Khắc phục vấn đề với setWebViewClient
Để mở đường dẫn mới với WebView thay vì trình duyệt web mặc định trong Android, thêm vào đoạn code sau:
webView.setWebViewClient(new WebViewClient());
Phương thức này chỉ định rằng mọi đường dẫn nhấn vào sẽ được tải lên và hiển thị trang web bởi WebView
chứ không sử dụng 1 trình duyệt web nào khác.
Các phương thức callback thường dùng khi thao tác với WebView
Trong khi sử dụng WebView
, cần 1 số event để có thể xử lý WebView
1 cách linh hoạt, ví dụ như các event liên quan đến tải trang started
, visible
, error
, finished
.
webView.setWebViewClient(new WebViewClient() { @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); } @Override public void onPageCommitVisible(WebView view, String url) { super.onPageCommitVisible(view, url); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); } @Override public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { super.onReceivedError(view, request, error); } @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { super.onReceivedError(view, errorCode, description, failingUrl); } });
Có 5 phương thức callback()
thường dùng:
onPageStart
onPageStart
là phương thức được gọi ngay sau khi gọi phương thức loadUrl()
của WebView
, thường sử dụng cho animation để làm tăng trải nghiệm người dùng.
onPageCommitVisible
onPageCommitVisible
là phương thức được gọi khi WebView
bắt đầu hiển thị trang web, thường sử dụng để kết thúc animation.
onPageFinished
onPageFinished
là phương thức được gọi khi WebView
đã hiển thị toàn bộ trang web, tải trang thành công.
onReceivedError
onReceivedError
là phương thức được gọi khi có lỗi xảy ra, ví dụ như không có mạng, đường dẫn không đúng, ... thường dùng cho việc tải lại trang hay xử lý UI (xử lý để che hình mặc định khi WebView
gặp lỗi).
Ngoài setWebViewClient
, có thể tạo 1 lớp riêng và override lại các phương thức callback vừa trên như dưới đây:
public class MyWebViewClient extends WebViewClient{ @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); } @Override public void onPageCommitVisible(WebView view, String url) { super.onPageCommitVisible(view, url); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); } @Override public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { super.onReceivedError(view, request, error); } @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { super.onReceivedError(view, errorCode, description, failingUrl); } }
Và setWebViewClient
như sau:
webView.setWebViewClient(new MyWebViewClient());
Ngoài những phương thức callback thường sử dụng, có 1 số phương thức callback nên biết.
@Override public void onFormResubmission(WebView view, Message dontResend, Message resend) { super.onFormResubmission(view, dontResend, resend); Log.e(TAG, "onFormResubmission: " ); } @Override public void onLoadResource(WebView view, String url) { super.onLoadResource(view, url); Log.e(TAG, "onLoadResource: " ); } @Override public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) { super.onReceivedClientCertRequest(view, request); Log.e(TAG, "onReceivedClientCertRequest: "); } @Override public void onReceivedLoginRequest(WebView view, String realm, String account, String args) { super.onReceivedLoginRequest(view, realm, account, args); Log.e(TAG, "onReceivedLoginRequest: "); } @Override public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) { super.onReceivedHttpAuthRequest(view, handler, host, realm); Log.e(TAG, "onReceivedHttpAuthRequest: " ); } @Override public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) { super.onReceivedHttpError(view, request, errorResponse); Log.e(TAG, "onReceivedHttpError: " ); } @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { super.onReceivedSslError(view, handler, error); Log.e(TAG, "onReceivedSslError: "); } @Override public void onScaleChanged(WebView view, float oldScale, float newScale) { super.onScaleChanged(view, oldScale, newScale); Log.e(TAG, "onScaleChanged: " ); } @Override public void onUnhandledKeyEvent(WebView view, KeyEvent event) { super.onUnhandledKeyEvent(view, event); Log.e(TAG, "onUnhandledKeyEvent: "); } @Override public void onTooManyRedirects(WebView view, Message cancelMsg, Message continueMsg) { super.onTooManyRedirects(view, cancelMsg, continueMsg); Log.e(TAG, "onTooManyRedirects: "); }
WebView Back Stack
1 vấn đề của WebView
hay gặp đó là vấn đề về Back Stack:
- Khi mở 1 đường dẫn thì được thêm vào Back Stack của
WebView
. - Nhưng khi nhấn trở lại thì gặp vấn đề
WebView
không trở lại trang trước đó.
Để xử lý trường hợp nàycần override
lại phương thức onBackPress()
như dưới đây:
@Override public void onBackPressed() { if (webView.canGoBack()) { webView.goBack(); } else { super.onBackPressed(); } }