I created an android WebView and open my website who server with https and authentication redirection anyway this work successfully in all of modern browsers like opera, chrome, Firefox , edge and eth but in android WebView i got 'too many redirect' error
By the way when I set WebView cache mode to none, this error had gone, but i need the cache mode,
Any body can help me?
Use this code to initialize webview and set url, it is work fine with me with all Android versions
#SuppressLint("SetJavaScriptEnabled")
private fun initWebView() {
webView.settings.javaScriptEnabled = true
webView.settings.loadsImagesAutomatically = true
webView.scrollBarStyle = View.SCROLLBARS_INSIDE_OVERLAY
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
}
private fun webViewListener() {
webView.webViewClient = object : WebViewClient() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
Log.d(TAG, url)
}
override fun onReceivedError(view: WebView, request: WebResourceRequest,
error: WebResourceError) {
super.onReceivedError(view, request, error)
//Error load url
}
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
//Loading url
view?.loadUrl(url)
return true
}
}
}
Add this line in Manifest File
<application
...
android:usesCleartextTraffic="true">
You can read more about usesCleartextTraffic
Related
I have a link to the PDF or XML file. By default, a web view doesn't render such links. From another StackOverflow post, I figured out I need to wrap by link by google doc or google drive link (http://docs.google.com/viewer?url=myPDFLink). It works, the web view displays content but not in all cases. For the same link, the content randomly might be not displayed or be displayed. If the page is not displayed I can just retry several times and content displays. Cannot find a reason for such behavior. Even if the web view is blank, the onPageFinished callback is being called but not any error callbacks.
Update: onPageStarted is not being called but onPageFinished is being
WebViewClient:
val webViewClient = object : WebViewClient() {
override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
updateOnBackPressedCallbackState()
toolbarActivity?.setToolBarTitle(url)
onPageStateListener?.onPageStarted(view, url)
}
override fun onPageFinished(view: WebView, url: String) {
super.onPageFinished(view, url)
progressBar?.visibility = View.GONE
toolbarActivity?.setToolBarTitle(view.title)
onPageStateListener?.onPageFinished(view)
}
override fun onReceivedError(
view: WebView?,
errorCode: Int,
description: String?,
failingUrl: String?
) {
super.onReceivedError(view, errorCode, description, failingUrl)
}
override fun onReceivedError(
view: WebView?,
request: WebResourceRequest?,
error: WebResourceError?
) {
super.onReceivedError(view, request, error)
}
override fun onReceivedHttpError(
view: WebView?,
request: WebResourceRequest?,
errorResponse: WebResourceResponse?
) {
super.onReceivedHttpError(view, request, errorResponse)
}
override fun onReceivedSslError(
view: WebView?,
handler: SslErrorHandler?,
error: SslError?
) {
super.onReceivedSslError(view, handler, error)
}
}
Settings:
webViewer.webViewClient = webViewClient
webViewer.settings.javaScriptEnabled = true
webViewer.isHorizontalScrollBarEnabled = true
webViewer.settings.mixedContentMode = WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE
Try to handle SSL errors within onReceivedSslError to proceed with the certificate
override fun onReceivedSslError(
view: WebView?,
handler: SslErrorHandler?,
error: SslError?
) =
if (handler != null) {
handler.proceed()
} else {
super.onReceivedSslError(view, handler, error)
}
I have a WebView in my app. It works properly but at Api 20, WebView does not show the content.
I checked the logs and see these errors
I/chromium: [INFO:CONSOLE(7)] "The key "shrink-to-fit" is not recognized and ignored.", source: https://...
I/chromium: [INFO:CONSOLE(43)] "Uncaught SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode", source: https://... (43)
I overviewed some answers and they generally suggest to use
webView.settings.useWideViewPort = true
webView.settings.loadWithOverviewMode = true
I have already implement these settings but still same error happens. WebView shows noting
Here is my WebView Settings
/**
* Initialize the WebView
*/
#SuppressLint("SetJavaScriptEnabled")
private fun initWebView() {
webView.webViewClient = object : WebViewClient() {
#RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
return super.shouldOverrideUrlLoading(view, request)
}
override fun onPageStarted(
view: WebView, url: String, favicon: Bitmap?) {
showProgressDialog()
}
override fun onPageFinished(view: WebView, url: String) {
hideProgressDialog()
}
#RequiresApi(api = Build.VERSION_CODES.M)
override fun onReceivedError(view: WebView, request: WebResourceRequest, error: WebResourceError) {
// Your code to do
hideProgressDialog()
}
override fun onReceivedError(view: WebView, errorCode: Int, description: String, failingUrl: String) {
// Handle the error
hideProgressDialog()
}
override fun onReceivedSslError(view: WebView, handler: SslErrorHandler?, error: SslError) {
// ignore ssl error
if (handler != null) {
handler.proceed()
} else {
super.onReceivedSslError(view, null, error)
}
}
}
webView.isHorizontalScrollBarEnabled = false
webView.settings.javaScriptEnabled = true
webView.settings.useWideViewPort = true
webView.setInitialScale(1)
webView.settings.loadWithOverviewMode = true
context?.let { webView.setBackgroundColor(ContextCompat.getColor(it, R.color.colorDarkBlue)) }
}
/**
* Load url
*/
private fun loadPage(url: String) {
webView.loadUrl(url)
}
Someone have a idea? I will be appreciate for any help
I need to load a proper site into webview.
What I do:
webView.setInitialScale(1)
webView.webViewClient = MyWebViewClient()
webView.settings.allowFileAccess = true
webView.settings.pluginState = WebSettings.PluginState.ON
webView.settings.pluginState = WebSettings.PluginState.ON_DEMAND
webView.settings.javaScriptEnabled = true
webView.settings.loadWithOverviewMode = true
webView.settings.useWideViewPort = true
for site
webView.loadUrl("https://pnpcss.com/vxyfv2ey/?subId1=fonev")
custom WebView:
private class MyWebViewClient : WebViewClient() {
#TargetApi(Build.VERSION_CODES.N)
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
view.loadUrl(request.url.toString())
return true
}
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
view.loadUrl(url)
return true
}
override fun onPageFinished(view: WebView?, url: String?) {
CookieManager.getInstance().getCookie(url)
super.onPageFinished(view, url)
}
}
What I have:
Only the bottom part of site is loaded, the upper is not. If I use chrome on this android phone, it is loaded ok.
Android versions tested: 5.0.1 & 8.
What I do wrong?
The problem was in that iframe was not loaded. It is solved with settings.domStorageEnabled = true
I am making an Android browser app, I want to handle link click that has target='_blank', which will open in a new tab in normal browsers.
There is a method call onCreateWindow in WebChromeClient which is triggering when a _blank link clicked. But my question is how can I get the link URL? following code is just returning the current URL
override fun onCreateWindow(view: WebView?, isDialog: Boolean, isUserGesture: Boolean, resultMsg: Message?): Boolean {
Toast.makeText(context, view?.url, Toast.LENGTH_LONG).show()
return super.onCreateWindow(view, isDialog, isUserGesture, resultMsg)
}
Finally, I found a way to capture the link URL.
#SuppressLint("SetJavaScriptEnabled")
override fun onCreateWindow(view: WebView?, isDialog: Boolean, isUserGesture: Boolean, resultMsg: Message?): Boolean {
val newWebView = WebView(context)
addView(context, newWebView)
val transport = resultMsg?.obj as WebView.WebViewTransport
transport.webView = newWebView
val settings = newWebView.getSettings()
settings.javaScriptEnabled = true
settings.javaScriptCanOpenWindowsAutomatically = true
settings.setSupportMultipleWindows(true)
settings.useWideViewPort = false
newWebView.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
}
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
Toast.makeText(context, url, Toast.LENGTH_LONG).show()
super.onPageStarted(view, url, favicon)
}
}
resultMsg.sendToTarget()
return true
}
By creating a new web and adding it to the WebViewTransport, you can add a new WebViewClient to that new WebView then its easy to capture that URL from onPageStarted method.
Solution must work on API >20
This solution does not work. I assume it works only on lower versions of the Android API. I'm testing on Android 8.0.
I've tried using Retrofit as soon as the page is loaded, instead of getting the html via WebViewClient. But the user is not logged in in the Retrofit request. And I'm doing the same request 2 times then.
#SuppressLint("JavascriptInterface")
private fun initializeWebView(url : String?) {
binding.webView.loadUrl(url)
binding.webView.settings.javaScriptEnabled = true
binding.webView.settings.useWideViewPort = true
binding.webView.requestFocus(View.FOCUS_DOWN)
binding.webView.addJavascriptInterface(MyJavaScriptInterface(context!!), "HtmlViewer");
binding.webView.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
return false
}
override fun onPageFinished(view: WebView?, url: String?) {
// super.onPageFinished(view, url)
//tried adding a sleep, but doesn't work:
Thread.sleep(6000)
//showHTML method is not being called:
binding.webView.loadUrl("javascript:window.HtmlViewer.showHTML" +
"('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');")
// Prints out: html: null
binding.webView.evaluateJavascript(
"javascript:window.HtmlViewer.showHTML" +
"('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');"
) { html ->
Log.d("HTML", html)
// code here
}
}
}
}
class MyJavaScriptInterface(val context: Context) {
fun showHTML(html: String) {
Log.d("",""+html)
AlertDialog.Builder(context).setTitle("HTML").setMessage(html)
.setPositiveButton(android.R.string.ok, null).setCancelable(false).create().show() }
}