我是Android开发的新手,这种行为很奇怪,或者可能是错误的结果。
我正在使用WebView创建一个应用程序,该应用程序加载了以前仅在浏览器中使用过的SPA:
我还添加了一个类,其中包含一些@JavascriptInterface
方法来处理网页和Android应用之间的通信。
网页使用Javascript调用location.reload()
,但WebView会忽略它。
我已经有了一个@JavascriptInterface
的类,然后让我们从网页中调用Activity的方法来处理webview.reload()
。
简单的想法,但是行不通。
奇怪的是,执行暂停(无论是在JS中还是在Android中)都没有任何错误,但是主线程并未停止,因为该应用程序仍然可以正常工作并响应事件。
答案 0 :(得分:0)
我认为这只是一种解决方法...但是可以。
在各种方法的完整执行之后,我使用了AsyncTask来延迟Activity中webview.reload()
的调用。
似乎Android webview.reload()
触发了某种异常,该异常在某个类内部的某个地方处理,此后什么也没有发生,只是下一行代码没有执行。
可能与他@JavascriptInterface
有关,或者我只是用脚开枪射击,看不见。
我需要Android方面更资深的专家的建议:比这个AsyncTask解决方案还优雅得多?
这是一个小型Android活动(Kotlin + XML布局)的代码,它将显示该问题。将它们粘贴到新的Android Studio项目中,按一些按钮,然后检查Logcat(过滤器“ 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>