Environment: Based on Android API-30

The WebView kernel is WebKit, and after version 4.4, it uses Chrome directly as the built-in web browser. Add network permission to manifest file (if read/write, add read/write) :

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Copy the code

As of API 28, plaintext support is disabled by default. HTTP urls cannot be loaded from webView.

android:usesCleartextTraffic="true"
Copy the code

Note:

5.1 The combination of HTTPS and HTTP is disabled by default. You can enable it as follows:
webView.settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
Copy the code

General use:

webView.settings.javaScriptEnabled = true
webView.webViewClient = object : WebViewClient() {
    override fun shouldOverrideUrlLoading(
        view: WebView? , request:WebResourceRequest?).: Boolean {
        if(request ! =null) { view? .loadUrl(request.url.toString()) }return true
    }
}
webView.loadUrl("http://www.baidu.com")
Copy the code

If you visit a web page that has Javascript, you must set it to support Javascript

webView.getSettings().setJavaScriptEnabled(true);
Copy the code

If you want to click the link in the webView to respond to the connection in the current Browser response instead of opening the Android browser, you need to override the WebViewClient of the webView:

webView.webViewClient = object : WebViewClient() {
    override fun shouldOverrideUrlLoading(
        view: WebView? , request:WebResourceRequest?).: Boolean {
        if(request ! =null) { view? .loadUrl(request.url.toString()) }return true}}Copy the code

Loading H5 mode:

// Load network H5
webView.loadUrl("http://www.baidu.com")
// Load h5 from assets
webView.loadUrl("file:///android_asset/test.html")
// To load the H5 of sdcard, read and write permission is required
webView.loadUrl("file:///xxx/test.html")
// Load the HTML snippet
val str = "<html><body>Hello <b>world</b></body></html>"
webView.loadData(str,"text/html".null)
Copy the code

Go forward/back to the stack

// Can I back up
webView.canGoBack()
// Back up the page
webView.goBack()

// Whether can advance
webView.canGoForward()
// Forward the page
webView.goForward()

// Use the current index as the starting point to move forward or backward to the steps specified in the history
// If steps is negative, steps are backward, and positive steps are forward
val step = 1
webView.goBackOrForward(step)
Copy the code

Clearing cached data

// Clear the cache left by web page visits
Since the kernel cache is global, this method applies not only to the WebView but to the entire application.
webView.clearCache(true)

// Clears the history of the current WebView access
// Only all records in the access history are cleared (except the current access record)
webView.clearHistory()

// This API only cleans up auto-filled form data, not WebView data stored locally
webView.clearFormData()
Copy the code

WebSettings class

val webSettings = webView.settings
// The WebView must be set up to support Javascript if the page to be accessed interacts with Javascript
// If the HTML is loaded and JS is performing animation and other operations, it will cause resource waste (CPU, battery).
// Set setJavaScriptEnabled() to false in onStop and true in onResume
webSettings.javaScriptEnabled = true
// Support plugin: deprecated, SystemApi, cannot be called directly
// webSettings.setPluginsEnabled(true)
// Set up the adaptive screen
webSettings.useWideViewPort = true // Resize the image to fit the WebView
webSettings.loadWithOverviewMode = true // Zoom to the size of the screen
// Zoom
webSettings.setSupportZoom(true) // Supports scaling and defaults to true. That's the premise of the following one.
webSettings.builtInZoomControls = true // Set the built-in zoom control. If false, the WebView is not scalable
webSettings.displayZoomControls = false // Hide the native zoom control
// Other details
webSettings.cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK // Disable the webView cache
webSettings.allowFileAccess = true // Set access to files
webSettings.javaScriptCanOpenWindowsAutomatically = true // Support to open new Windows through JS
webSettings.loadsImagesAutomatically = true // Support automatic loading of images
webSettings.defaultTextEncodingName = "utf-8" // Set the encoding format
Copy the code

Set up the WebView cache

  • When loading HTML pages, WebView generates database and cache folders in the /data/data/ package name directory
  • The requested URL record is stored in webViewCache.db, and the URL content is stored in WebViewCache

Use cache or not:

// Use cache first:
webSettings.cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK
// Cache mode is as follows:
//LOAD_CACHE_ONLY: no network is used, only local cached data is read
//LOAD_DEFAULT: (default) Cache-control determines whether to fetch data from the network.
//LOAD_NO_CACHE: does not use cache, only gets data from the network.
//LOAD_CACHE_ELSE_NETWORK, as long as there is local, regardless of expiration, or no-cache, use the data in the cache.
// Do not use cache:
webSettings.cacheMode = WebSettings.LOAD_NO_CACHE
Copy the code

Offline loading:

if (isConnected(applicationContext)) {
    webSettings.cacheMode = WebSettings.LOAD_DEFAULT Cache-control determines whether to fetch data from the network.
} else {
    webSettings.cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK // If there is no network, load it from the local directory
}
webSettings.domStorageEnabled = true // Enable DOM storage API function
webSettings.databaseEnabled = true // Enable the database Storage API
webSettings.setAppCacheEnabled(true) // Enable Application Caches; Have been abandoned
val cacheDirPath = filesDir.absolutePath + APP_CACAHE_DIRNAME
webSettings.setAppCachePath(cacheDirPath) // Set the Application Caches directory; Have been abandoned
Copy the code

Note: each Application. Just call a webSettings setAppCachePath, webSettings. SetAppCacheMaxSize ()

WebViewClient class

ShouldOverrideUrlLoading is displayed locally or in the system browser; Urls can be intercepted for processing.

webView.webViewClient = object : WebViewClient() {
    override fun shouldOverrideUrlLoading(
        view: WebView? , request:WebResourceRequest?).: Boolean {
        if(request ! =null) { view? .loadUrl(request.url.toString()) }return true}}Copy the code

Start a callback to load the page. You can load the page and wait for the network to respond.

override fun onPageStarted(view: WebView? , url:String? , favicon:Bitmap?). {
    // Load the operation started
}
Copy the code

End of load callback. You can disable loading.

override fun onPageFinished(view: WebView? , url:String?). {
    // Load the finished operation
}
Copy the code

The load resource callback is called once for each load of a resource such as an image

override fun onLoadResource(view: WebView? , url:String?). {
    // Load resources
}
Copy the code

An error occurred while loading the page (e.g. 404), we can load a local error page instead of the ugly system page. Net ::ERR_NAME_NOT_RESOLVED error can be reported when no network is available. Note, however: multiple error callbacks are possible.

override fun onReceivedError(
view: WebView? , request:WebResourceRequest? , error:WebResourceError?). {
super.onReceivedError(view, request, error)
}
Copy the code

WebView does not process HTTPS requests by default, and the page displays blank.

override fun onReceivedSslError(
view: WebView? , handler:SslErrorHandler? , error:SslError?). {
if(handler ! =null) {
    handler.proceed()// Wait for the certificate response
    handler.cancel()// Suspend the connection, default
    handler.handleMessage(handler.obtainMessage())// Do other processing}}Copy the code

WebChromeClient class

Get the page loading progress and display:

override fun onProgressChanged(view: WebView? , newProgress:Int){}Copy the code

Gets the title in the Web page

override fun onReceivedTitle(view: WebView? , title:String?).{}Copy the code

JavaScript alert, intercepting JS alert to convert native dialog

override fun onJsAlert(
    view: WebView? , url:String? , message:String? , result:JsResult?).: Boolean {
    return true
}
Copy the code

JavaScript confirmation box

override fun onJsConfirm(
    view: WebView? , url:String? , message:String? , result:JsResult?).: Boolean {
    // return ture to confirm; Return false to cancel
    return super.onJsConfirm(view, url, message, result)
}
Copy the code

JavaScript input box, click Ok to return the value in the input box, click Cancel to return NULL

override fun onJsPrompt(
    view: WebView? , url:String? , message:String? , defaultValue:String? , result:JsPromptResult?).: Boolean {
    return super.onJsPrompt(view, url, message, defaultValue, result)
}
Copy the code

Avoid WebView memory leaks

Instead of defining webViews in XML, create them in the Activity when needed, and use getApplicationContext().

val param = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT)
var myWebView = WebView(applicationContext)
myWebView.layoutParams = param
rootView.addView(webView)
Copy the code

When an activity destroys a WebView, the WebView loads the NULL content, then removes the WebView, then destroys the WebView, and then sets null

override fun onDestroy(a) {
    if(webView ! =null) {
        webView.loadDataWithBaseURL(null.""."text/html"."utf-8".null)
        webView.clearHistory()
        (webView.parent as ViewGroup).removeView(webView)
        webView.destroy()
    }
    super.onDestroy()
}
Copy the code

FAQ:

Problem: github.com/gzsll/WebVi…

Memory leak:

  1. WVJWebViewClientProxy leak
  2. MessageHandlers under WVJBWebView leak

Solution:

// Add unregister to the WVJBWebView class
public void unregisterAllHandler() {
    messageHandlers.clear();
}
// When the webView is destroyed (for example, onDestroy of the activity needs to be called)webView!! .unregisterAllHandler() webView!! .clientProxy =null
Copy the code

Data parsing is abnormal, especially special characters in interaction between H5 and Native. For example, h5 sends a message to native. “””” json contains double quotation marks, but the message cannot be parsed and transmitted. Suggestion: Do not use this library in your project