Unable to reload Android WebView from Javascript

前端 未结 1 1129
心在旅途
心在旅途 2021-01-29 00:16

I\'m quite new to the Android Development and this behaviour is quite weird or could be a result of a bug.

Project description

I\'m creating an App with a WebV

相关标签:
1条回答
  • 2021-01-29 01:20

    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?

    Test Project

    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').

    MainActivity.kt

    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")
        }
    }
    

    activity_main.xml

    <?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>
    
    0 讨论(0)
提交回复
热议问题