Android Webview即使设置了setJavascriptEnabled(true)和WebChromeClient也会跳过JavaScript

8
(使用三星Galaxy Tab和Android 3.0,此应用程序旨在适用于所有3.0+平板电脑,就像在其浏览器中一样,但不适用于Webview)。
我有一个带有CSS和jQuery的页面,在浏览器、Android浏览器和iOS设备中可以正常加载,但是Android Webview无法始终加载它。
我通过复制一些Webview JavaScript演示应用程序来缩小了问题范围,发现问题是它在加载时简单地跳过了JavaScript。为什么会这样呢?
以下是完整的测试HTML代码:http://pastebin.com/GmE2vEYx
这是我的调用方式:
  myWebview.loadUrl("file:///android_asset/myPage.html");
  myWebview.getSettings().setJavaScriptEnabled(true);
  myWebview.setWebChromeClient(new WebChromeClient());

这三个调用的顺序不影响结果。
  myWebview.getSettings().setJavaScriptEnabled(true);
  myWebview.setWebChromeClient(new WebChromeClient());
  myWebview.loadUrl("file:///android_asset/myPage.html");

我注意到的一件事是,如果你给它时间(通过在调试器中使用断点来暂停应用程序),那么javascript会更加稳定地加载。这引导我进行了一些牵强的实验,试图使应用程序加载得更慢,但这确实不是期望的用户体验。我真的希望Android webview不是移动开发的IE6。
其他事实:
如果删除包含所有Jquery的<script>标签,则页面将快速加载所有CSS格式。只要添加了Jquery,就什么都不加载。
我还发现了几个遇到完全相同问题的问题,许多问题没有得到答复或没有得出OP所寻求的结论 :(
参见: Android:即使设置了setJavaScriptEnabled(true),也无法在WebView上使javascript正常工作 页面重新加载(Webview.loadUrl)导致Javascript未被(完全)处理

http://groups.google.com/group/android-developers/browse_thread/thread/9962064ef217a5a7#

在Android的Webview中,JavaScript有时无法正常工作

Android WebView无法加载JavaScript文件,但Android浏览器可以正常加载它

Android的Webview无法处理javascript?

有什么建议吗?让我们找到问题的根源! Android文档说Webview有限制,但我不知道这个限制在哪里,因为人们经常制作HTML CSS JS应用程序!


1
如果JS存在错误,它应该在adb logcat中显示,标签为“Web Console”或“WebCore”。您的页面上是否有任何JS错误? - NoBugs
4个回答

4
我也拥有三星Galaxy Tab和安卓3.0平板电脑,以及使用jQuery JavaScript的网页,可以正常运行。请确保您的网页在Chrome浏览器中运行,并且没有JavaScript错误。一些CSS3样式(例如图像消失)已知存在问题,但是jQuery应该可以正常工作。如果您尝试与JavaScript通信,请确保在页面加载后进行操作。同时,请确保所有文件位于正确的目录中 :)。有时内容会被缓存,因此请尝试删除缓存(或删除应用程序)。
请提供您的网页源代码,以便我们检查。
示例Webview:
webView = (WebView) findViewById(R.id.webview);

WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setPluginsEnabled(true);
webSettings.setLoadsImagesAutomatically(true);
webSettings.setSupportZoom(false);

webView.setScrollBarStyle(WebView.SCROLLBARS_INSIDE_OVERLAY);
webView.setWebViewClient(new WebViewClient()
{
    @Override
    public void onPageFinished(WebView view, String url) 
    {
        // page loaded...
        super.onPageFinished(view, url);
    }
});
webView.setWebChromeClient(new WebChromeClient()
{
    @Override
    public boolean onJsAlert(WebView view, String url, String message,JsResult result) 
    {
        Log.e("alert triggered", message);
        return false;         
    }
});
webView.loadUrl("http://mypage/mypage.html");

我会尽力完成翻译工作。以下是您需要翻译的内容:

希望能对您有所帮助。

更新1: 我在三星Galaxy平板电脑上测试了您的代码。我进行了以下更改:

<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.2.min.js"></script>

第一行。页面已加载,我可以看到带图片的内容。所以……代码按预期工作。

我注意到有时内容显示不正常。似乎缩放是问题所在:

<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, user-scalable=no" />

而且$(document).ready()内的计算结果为false!

顺便说一下...你要找的是带有WebView的ViewPager。

更新2:请注意,当以file:///方式加载网页时,必须将JS文件放在同一目录中(无外部URL)。


好的,我已经将它缩小到了几行代码:$('body').css({height : height+'px', width : Math.floor(width*0.98)+'px' }); $('.text').css({height : height+'px', width : Math.floor(width*0.98)+'px' }); $('#firstpage').css({height : height+'px', width : Math.floor(width*0.98)+'px' }); $('body').prepend('<style>.text{-moz-column-count:'+numCols+';-webkit-column-count:'+numCols+';}</style>'); 没有这些代码,整个页面都可以正常加载,但是这些代码非常重要,因此我会寻找更好的方法来实现同样的功能(它可以动态地将页面分成多列)。 - CQM
嘿...你能提供一个URL吗?你在Crome中检查过了吗?有出现任何错误吗?你是如何加载jQuery的(在哪里)? - xpepermint
URL已经提供在pastebin上,你需要在自己的机器上测试它。JQuery从assets文件夹本地加载,我已确认它可以工作,因为滑动功能可以正常使用。在Chrome中检查过,没有错误。 - CQM
你说的document ready里面的计算是什么意思?哪一个计算?此外,meta标签应该放在script标签的上方还是下方(我没有得到不同的结果)。你能详细说明一下ViewPager和webviews吗? - CQM

4
答案是JavaScript需要在HTML页面的<script>部分中以函数的形式存在,并且需要通过webview.loadUrl("javascript:yourJavascriptFunction()")注入,此前需要使用webview.setWebviewClient(new WebviewClient(){ public void onPageFinishedLoading(){ ...//js injections here });

2

我曾经遇到过同样的问题,很久以前 - 我的最终解决方案是放弃jquery,只使用纯JS。当在正常的Android浏览器中查看时,一切都运行良好,但事情不断地出现问题。

如果这些是唯一破坏代码的行,请尝试使用纯JS复制这些行的相同功能。 Android的原生Webview对所有最新的JS功能都有很好的支持,

所以...

$('body').css({height : height+'px', width : Math.floor(width*0.98)+'px' });
$('.text').css({height : height+'px', width : Math.floor(width*0.98)+'px' }); 
$('#firstpage').css({height : height+'px', width : Math.floor(width*0.98)+'px' }); 
$('body').prepend('<style>.text{-moz-column-count:'+numCols+';-webkit-column-count:'+numCols+';}</style>'); 

将会是...

var doc = document,
    body = doc.getElementsByTagName('body')[0],
    bodyStyle = body.style,
    firstPage = doc.getElementById('firstpage'),
    firstPageStyle = firstPage.style,

    head = doc.getElementsByTagName('head')[0],
    style = doc.createElement('style'),
    rules = doc.createTextNode('.text{-webkit-column-count:'+numCols+';}');

bodyStyle.height = height + 'px';
bodyStyle.width = Math.floor(width * 0.98) + 'px';

firstPageStyle.height = height + 'px';
bodyStyle.width = Math.floor(width * 0.98) + 'px';

style.type = 'text/css';

if( style.styleSheet )
    style.styleSheet.cssText = rules.nodeValue;
else 
    style.appendChild( rules );

head.appendChild( style );

请确保上述代码在所有使用的元素加载后运行(DOM就绪状态后或在闭合标签之前)。

顺便提一下,既然你正在使用Android的Webkit,为什么还需要-moz-column-count?


你能详细说明一下这个语法应该如何工作吗?它在 jslint.com 上都失败了。我的原始代码有 $(document).ready(function(){....}); ,我认为你的 js 版本应该放在这个函数内部,但如果我完全切换到 js,则我认为我的函数“声明”现在将有所不同。 - CQM
$(document).ready(function(){....})基本上确保了包含在ready函数的匿名回调中的代码将在DOM加载后运行。同样的效果也可以通过在body标记结束前添加脚本来实现。只要"width"变量被设置,我分享的代码应该在document ready中正常工作,因为那些是唯一的“缺失”值。我只是将你发布的jQuery代码翻译成了常规JS。 - Pantelis
关于jslint,“第22行第5个字符存在问题:else和style之间应该只有一个空格。”和“第21行第1个字符存在问题:在第5列而不是第1列期望有'else'。”大部分都是简单的缩进错误,很容易纠正。唯一的“危险”是“width”变量,我相信它已经在您现有的代码中声明了,所以那里不应该有问题:) - Pantelis

1

我不完全确定这是否是您问题的原因,但在设置WebView后应该调用loadUrl

编辑

如果这不是问题,请考虑发布以下信息:

  • 您找到的最简单的SSCCE(您认为应该工作但却不起作用)
  • 您的设备型号和您使用的Android版本

@RD 没有你的实际代码,任何人都很难回答。此外,发布你正在使用的设备的制造/型号可能会引起曾经遇到过设备特定问题的人的建议。 - no.good.at.coding
三星Galaxy Tab,但最好是所有Honeycomb 3.0+设备。 - CQM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接