I\'m quite new to the Android Development and this behaviour is quite weird or could be a result of a bug.
I\'m creating an App with a WebV
I think is just a workaround...but works.
I've used an AsyncTask to delay the call of webview.reload()
in the Activity after the complete executions of the various methods.
Seems that the Android webview.reload()
triggers some sort of exception that is handled somewhere inside some class and nothing happens after, simply the next the line of code isn't executed.
Probably is something connected to he @JavascriptInterface
or I'm just shooting myself in the foot and I can't see it.
I need an advice from someone more expert in Android: there is something much more elegant than this AsyncTask solution?
Here is the code of a small Android Activity (Kotlin+XML Layout) that will show the problem. Paste them in an new Android Studio project, press some buttons and check Logcat (filter 'PNK').
package it.punkman.webviewreloadbug
import android.os.AsyncTask
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.webkit.JavascriptInterface
import android.webkit.WebChromeClient
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
class JSInterface(val mainActivity: MainActivity){
private inner class Reloader : AsyncTask<Int, Void, Int>() {
override fun doInBackground(vararg params: Int?): Int {
Thread.sleep(500)
return 0
}
override fun onPostExecute(result: Int?) {
super.onPostExecute(result)
Log.d("PNK","Android - Reload Async Real execute!")
mainActivity.refreshWebView(mainActivity.btnRefresh)
Toast.makeText(mainActivity,"WebView refreshed! OK!",Toast.LENGTH_LONG).show(); //OK
}
}
@JavascriptInterface
fun reloadBug(){
Log.d("PNK","Android - Reload Bug Start")
mainActivity.refreshWebView(mainActivity.btnRefresh)
Log.d("PNK","Android - Reload Bug End")
Toast.makeText(mainActivity,"You cannot see this toast!",Toast.LENGTH_LONG).show(); //Unable to see
}
@JavascriptInterface
fun reloadAsync(){
Log.d("PNK","Android - Reload Async Start")
Reloader().execute(0,null,0)
Log.d("PNK","Android - Reload Async Stop")
}
}
val HTML_SAMPLE_PAGE="""
<!DOCTYPE html>
<html>
<head>
<script>
function refreshPage(){
alert("DOM - Refresh Start");
location.reload(); //Inside an Android WebView this isn't working!
alert("DOM - Refresh End\nNothing refreshed, reload ignored");
}
function refreshPageJSI_Bug(){
alert("JS Interface - Refresh Start");
JSI.reloadBug()
alert("JS Interface - Refresh End NEVER SHOWN!"); //NEVER SHOWN!
}
function refreshPageJSI_Async(){
alert("JS Interface - Refresh Start Async");
JSI.reloadAsync()
alert("JS Interface - Refresh End Async");
}
</script>
</head>
<body>
<script>document.write(new Date())</script>
<br/><br/>
<button style="width:100%" onclick="refreshPage()">HTML - JS Refresh</button><br/><br/>
<button style="width:100%" onclick="refreshPageJSI_Bug()">HTML - JavascriptInterface BUG?</button><br/><br/>
<button style="width:100%" onclick="refreshPageJSI_Async()">HTML - JavascriptInterface with AsyncTask</button>
</body>
</html>
"""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// For the purpose of this example
// the page is just injected from a string
// but the result is the same
testWebView.settings.javaScriptEnabled=true
testWebView.webChromeClient = WebChromeClient()
testWebView.addJavascriptInterface( JSInterface(this), "JSI")
testWebView.loadData(HTML_SAMPLE_PAGE,"text/html",null)
}
fun refreshWebView(v:View){
Log.d("PNK","Android - Refresh Start")
testWebView.reload()
// OR again using loadUrl - testWebView.loadUrl(HTML_SAMPLE_PAGE)
Log.d("PNK","Android - Refresh End")
}
}
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" tools:layout_editor_absoluteY="8dp"
tools:layout_editor_absoluteX="8dp">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="50dp">
<Button
android:layout_width="match_parent"
android:layout_height="50dp"
android:onClick="refreshWebView"
android:text="Android - Refresh"
android:id="@+id/btnRefresh"/>
</LinearLayout>
<WebView
android:layout_width="match_parent"
android:layout_height="match_parent" android:id="@+id/testWebView"/>
</LinearLayout>
</android.support.constraint.ConstraintLayout>