Невозможно перезагрузить Android WebView из Javascript - PullRequest
0 голосов
/ 02 мая 2019

Я довольно новичок в разработке Android, и это поведение довольно странное или может быть результатом ошибки.

Описание проекта

Я создаю приложение с WebViewкоторые загружают SPA, который ранее использовался только в браузерах:

  • Я включил Javascript для WebView
  • Я понял, что для приобретения некоторых основных функций JS (например, alert ()),должен быть установлен WebChromeClient.

Я также добавил класс с некоторыми @JavascriptInterface методами для обработки связи между веб-страницей и приложением Android.

Проблема

Веб-страница вызывает location.reload() в Javascript, но это игнорируется WebView.

Неудачное решение

У меня уже есть класс с @JavascriptInterface впоместите, а затем вызовем метод Activity с веб-страницы для обработки простой идеи webview.reload().
, но она не работает.

Странно то, что выполнение просто останавливается (как в JS, так и в JS).в Android) без каких-либо ошибок, кроме майПоток n не останавливается, потому что приложение все еще работает и отвечает на события.

1 Ответ

0 голосов
/ 02 мая 2019

Я думаю, что это просто обходной путь ... но работает.

Я использовал AsyncTask для задержки вызова webview.reload() в Activity после полного выполнения различных методов.

Кажется, что Android webview.reload() вызывает какое-то исключение, которое обрабатывается где-то внутри некоторого класса, и после этого ничего не происходит, просто следующая строка кода не выполняется. Возможно, что-то связано с ним @JavascriptInterface, или я просто стреляю себе в ногу, и я не вижу этого.

Мне нужен совет от кого-то более опытного в Android: есть что-то намного более элегантное, чем это решение AsyncTask?

Тестовый проект

Вот код небольшого Android Activity (Kotlin + XML Layout), который покажет проблему. Вставьте их в новый проект Android Studio, нажмите несколько кнопок и отметьте Logcat (фильтр «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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...