WebView is an Android element that enables builders to show a webpage in an app.
There are varied eventualities wherein WebView may be helpful. For instance, it might be used to show a standard web page between Internet and Android, like a “Phrases & Privateness” web page. It may be used to show a web page, thereby avoiding a community request, after which parse the info to show it in an Android format.
Chances are you’ll be considering that should you can show a webpage in an Android app, then you’ll be able to construct your personal browser app!
Nicely, by default, WebView has just one purpose – to indicate a webpage. It doesn’t embrace options like an actual net browser, similar to navigation controls or an tackle bar. However, if it’s a View, and you’ll embrace it in an exercise format, then you may as well embrace your personal controls.
On this article, we’ll share options to widespread issues that Android builders usually encounter when utilizing a WebView, similar to find out how to customise Android’s again button navigation. All the code on this article is Kotlin.
Soar forward:
Dealing with web page navigation and web page reload if there’s no content material
When a person clicks on a hyperlink inside a WebView, the Android working system will attempt to open it in an exterior utility that may deal with URLs, similar to a browser:
To permit the person to navigate by way of their webpage historical past, you’ll want to supply a WebViewClient to the WebView:
val myWebView: WebView = findViewById(R.id.webview) myWebView.webViewClient = WebViewClient()
As a substitute of utilizing the default WebViewClient
, you may as well implement your personal, like so:
myWebView.webViewClient = object : WebViewClient() { … }
Two of essentially the most generally overridden behaviors of WebViewClient
, are onPageStarted
and onPageFinished
.
myWebView.webViewClient = object : WebViewClient() { override enjoyable onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { tremendous.onPageStarted(view, url, favicon) } override enjoyable onPageFinished(view: WebView?, url: String?) { tremendous.onPageFinished(view, url) } }
Utilizing these two strategies, you’ll be able to perceive when the web page has began and completed loading and you will get entry to the URL.
One widespread implementation of onPageFinished
is to refresh the webpage if the content material peak is 0
when the web page is completed loading, since this might point out that one thing went unsuitable (e.g., a PDF might have did not load on the WebView):
myWebView.webViewClient = object : WebViewClient() { override enjoyable onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { tremendous.onPageStarted(view, url, favicon) } override enjoyable onPageFinished(view: WebView?, url: String?) { if (view?.contentHeight == 0) { view.reload() } else { tremendous.onPageFinished(view, url) } } }
Dealing with again button navigation
As defined beforehand, a WebView doesn’t deliver inbuilt navigation controls. When you have a web page opened and also you click on on Android’s again button, it is not going to go to the beforehand visited web page on the WebView. As a substitute, it would navigate inside the applying itself, as proven beneath:
Normally, WebViews are carried out on their very own exercise. To repair this, we’ll must take a detailed take a look at the exercise behaviors that we’re in a position to entry.
Exercise class supplies varied methods to override and customise behaviors. One instance is onKeyDown
; this methodology will get known as when a key’s pressed.
We will use this methodology to detect when a person presses the system’s again button. Right here’s an instance:
override enjoyable onKeyDown(keyCode: Int, occasion: KeyEvent?): Boolean { if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) { webView.goBack() return true } // If it wasn't the Again key or there is no webpage historical past, bubble as much as the default // system habits (in all probability exit the exercise) return tremendous.onKeyDown(keyCode, occasion) }
WebView supplies some useful utility strategies, similar to canGoBack
and goBack
.
We will use canGoBack
to seek out out if a web page was beforehand loaded. We will use goBack
to load the earlier web page:
if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack())
The above code checks if the pressed key’s the system’s again button and if any web page was loaded earlier than the button was pressed. If the result’s optimistic, the goBack
methodology is named.
onKeyDown
returns a Boolean worth. If we need to override the habits, we return true
; in any other case, we return false
.
By including this code inside our exercise, we should always see the next habits:
Analyzing accessed URLs
There are some eventualities the place we’d need to redirect the person to exterior purposes. For instance, we might need to allow the person to open a PDF.
To make this attainable, WebViewClient supplies one other methodology that may be overridden, known as shouldOverrideUrlLoading
:
myWebView.webViewClient = object : WebViewClient() { override enjoyable shouldOverrideUrlLoading( view: WebView?, request: WebResourceRequest? ): Boolean { … return tremendous.shouldOverrideUrlLoading(view, request) } }
This methodology might be known as each time a brand new URL is being loaded. This enables us to test what URL is being loaded and react accordingly:
myWebView.webViewClient = object : WebViewClient() { override enjoyable shouldOverrideUrlLoading( view: WebView?, request: WebResourceRequest? ): Boolean { view?.url?.let { url -> if (url.endsWith(".pdf")) { startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url))) return true } } return tremendous.shouldOverrideUrlLoading(view, request) } }
WebView has a property known as url
that corresponds to the presently loaded URL. We will take this property and make sure if the URL ends with the PDF extension, like so:
if (url.endsWith(".pdf"))
If the URL does finish with .pdf
, we delegate it to the working system to seek out an app that may deal with that kind of URL. The worth of true
have to be returned each time we need to override shouldOverrideUrlLoading
.
Displaying a loading display screen whereas the web page hundreds
To enhance person expertise, we are able to present a method to let the person know {that a} web page remains to be loading. We will do that by overriding onPageStarted
and onPageFinished
on WebViewClient
, like so:
myWebView.webViewClient = object : WebViewClient() { override enjoyable onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { tremendous.onPageStarted(view, url, favicon) } override enjoyable onPageFinished(view: WebView?, url: String?) { tremendous.onPageFinished(view, url) } }
Assuming you’ve gotten a method to show a loading display screen, similar to a popup containing a progress bar, you’ll be able to present and dismiss the loading display screen on onPageStarted
and onPageFinished
, respectively.
Right here’s an instance:
myWebView.webViewClient = object : WebViewClient() { override enjoyable onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { tremendous.onPageStarted(view, url, favicon) showLoading() } override enjoyable onPageFinished(view: WebView?, url: String?) { tremendous.onPageFinished(view, url) dismissLoading() } }
Dealing with render course of crashes
One other widespread drawback is when the WebView’s render course of crashes. This may occur both as a result of the system killed the renderer to reclaim much-needed reminiscence or as a result of the render course of itself crashed.
You’ll often know you’re coping with this drawback if the crash stack hint incorporates the next message:
Render course of's crash wasn't dealt with by all related webviews, triggering utility crash.
The error message may additionally cite the processId
.
To make sure person expertise isn’t negatively impacted, the crash have to be dealt with, in any other case the applying will shut down.
Extra nice articles from LogRocket:
After this error happens, the related occasion of WebView can’t be reused. As a substitute, it have to be destroyed and faraway from the view hierarchy, and a brand new occasion of WebView have to be created.
If the render course of crashes whereas accessing a selected webpage, trying to load the identical web page might trigger the identical problem.
To deal with this drawback, we have to override onRenderProcessGone
on WebViewClient
, like so:
myWebView.webViewClient = object : WebViewClient() { override enjoyable onRenderProcessGone(view: WebView, element: RenderProcessGoneDetail): Boolean { if (!element.didCrash()) { Log.e("MY_APP_TAG", ("System killed the WebView rendering course of " + "to reclaim reminiscence. Recreating...")) myWebView?.additionally { webView -> val webViewContainer: ViewGroup = findViewById(R.id.my_web_view_container) webViewContainer.removeView(webView) webView.destroy() myWebView = null } // By this level, the occasion variable "myWebView" is assured // to be null, so it is secure to reinitialize it. return true // The app continues executing. } Log.e("MY_APP_TAG", "The WebView rendering course of crashed!") return false } }
If RenderProcessGoneDetail
didCrash()
returns a worth of false
, which means the method was killed as a result of the system ran out of reminiscence. On this state of affairs, the app can recuperate gracefully by creating a brand new WebView occasion.
When a worth of true
is returned from onRenderProcessGone
, it means we need to preserve the app operating as a substitute of closing it as a result of crash.
If RenderProcessGoneDetail
didCrash()
returns a worth of true
, it means the method was killed on account of an inner error, similar to a reminiscence entry violation. Should you return false
on this case, the app will crash after detecting that the renderer crashed.
To deal with the crash extra gracefully and permit the app to maintain executing, observe these steps:
- Destroy the present WebView occasion
- Specify the logic for a way the app can proceed executing
- Return
true
fromonRenderProcessGone
Conclusion
On this article, we investigated and provided options for a few of the commonest issues the Android builders encounter when utilizing WebView. Particularly, we checked out find out how to: customise Android’s again button navigation with WebView, deal with web page navigation and web page reload if there’s no content material, analyze accessed URLs, present a loading display screen whereas a web page hundreds, and deal with render course of crashes.
To study extra about WebView, take a look at the official documentation for constructing net apps in WebView and managing WebView objects.
LogRocket: Full visibility into your net and cell apps
LogRocket is a frontend utility monitoring resolution that permits you to replay issues as in the event that they occurred in your personal browser. As a substitute of guessing why errors occur, or asking customers for screenshots and log dumps, LogRocket permits you to replay the session to shortly perceive what went unsuitable. It really works completely with any app, no matter framework, and has plugins to log further context from Redux, Vuex, and @ngrx/retailer.
Along with logging Redux actions and state, LogRocket information console logs, JavaScript errors, stacktraces, community requests/responses with headers + our bodies, browser metadata, and customized logs. It additionally devices the DOM to report the HTML and CSS on the web page, recreating pixel-perfect movies of even essentially the most complicated single-page and cell apps.