>source

Android 개발에 익숙하지 않으며이 동작은 매우 이상하거나 버그의 결과 일 수 있습니다.

프로젝트 설명

이전에 브라우저에서만 사용되었던 SPA를로드하는 WebView로 앱을 만들고 있습니다 :

  • WebView에 자바 스크립트를 활성화했습니다
  • 기본 JS 함수 (예 : alert ())를 얻으려면 WebChromeClient를 설정해야한다는 것을 이해했습니다.

저도 @JavascriptInterface 클래스를 추가했습니다  웹 페이지와 Android 앱 간의 통신을 처리하는 방법

문제

웹 페이지 location.reload()  자바 스크립트에서는 WebView에서 무시됩니다.

실패한 솔루션

나는 이미 @JavascriptInterface 와 함께 수업을했습니다  그런 다음 웹 페이지에서 활동의 메소드를 호출하여 webview.reload() 를 처리합시다.
간단한 생각이지만 작동하지 않습니다.

이상한 점은 어떤 종류의 오류없이 실행이 중단 (JS 및 Android 모두)되지만 응용 프로그램이 여전히 작동하고 이벤트에 응답하기 때문에 메인 스레드가 중지되지 않는다는 것입니다.


  • 답변 # 1

    해결책 일 뿐이지 만 효과가 있다고 생각합니다.

    webview.reload() 의 호출을 지연시키기 위해 AsyncTask를 사용했습니다  다양한 메소드가 완전히 실행 된 후 활동에 표시됩니다.

    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>
    
    

관련 자료

  • 이전 c# - JSON을 객체 목록으로 구문 분석하고 콘솔에 데이터 표시
  • 다음 java - split ("\")이 작동하지 않으며 오류 arrayindexoitofboundsexception - 1