Android 9及以下WebView加载网页JS报语法错误,10+正常如何解决?
问题
我需要将工作中的网站封装到WebView中,要求支持Android 8及以上版本。代码如下:
布局代码
<?xml version="1.0" encoding="utf-8"?> <WebView android:id="@+id/webContent" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:android="http://schemas.android.com/apk/res/android" />
Activity代码
class MainActivity : AppCompatActivity() { @SuppressLint("SetJavaScriptEnabled") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val webView = findViewById<WebView>(R.id.webContent) webView.settings.javaScriptEnabled = true webView.settings.domStorageEnabled = true webView.webViewClient = WebViewClient() webView.webChromeClient = WebChromeClient() val url = getString(R.string.url_to_load) webView.loadUrl(url) } }
在Android 10及以上版本运行时页面加载正常,但Android 9及以下版本会出现页面渲染失败,日志输出:
"Uncaught SyntaxError: Unexpected token .", source: https://mysite/_next/static/chunks/pages/_app-a67da37c3cc054e4.js (15)
推测问题源于网站JS使用了Android 9及以下WebView不支持的ECMAScript特性,求无需修改网站JS的解决办法。
解决办法
1. 开启WebView兼容配置
Android 9及以下系统WebView对新ES语法支持有限,通过以下配置可提升兼容性:
@SuppressLint("SetJavaScriptEnabled") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val webView = findViewById<WebView>(R.id.webContent) val settings = webView.settings settings.javaScriptEnabled = true settings.domStorageEnabled = true settings.javaScriptCanOpenWindowsAutomatically = true settings.renderPriority = WebSettings.RenderPriority.HIGH // 处理混合内容(若网站存在HTTPS+HTTP资源) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { settings.mixedContentMode = WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE } webView.webViewClient = WebViewClient() webView.webChromeClient = WebChromeClient() val url = getString(R.string.url_to_load) webView.loadUrl(url) }
2. 升级AndroidX WebView依赖
Google持续更新AndroidX WebView的内核,提升对新JS特性的支持。在模块级build.gradle中更新依赖:
dependencies { implementation 'androidx.webkit:webkit:1.6.0' // 使用最新稳定版本 }
使用WebViewCompat做兼容配置:
import androidx.webkit.WebSettingsCompat import androidx.webkit.WebViewFeature // 初始化WebView后添加以下配置 val settings = webView.settings if (WebViewFeature.isFeatureSupported(WebViewFeature.JAVASCRIPT_ENABLED)) { WebSettingsCompat.setJavaScriptEnabled(settings, true) } if (WebViewFeature.isFeatureSupported(WebViewFeature.DOM_STORAGE_ENABLED)) { WebSettingsCompat.setDomStorageEnabled(settings, true) }
3. 预注入Polyfill脚本
在页面加载前注入Polyfill,填补低版本WebView缺失的ES特性(比如报错的可选链操作符?.)。可以将成熟的Polyfill库(如core-js精简版)保存为本地assets/polyfill.js文件,然后在加载网站前执行:
webView.webViewClient = object : WebViewClient() { override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { super.onPageStarted(view, url, favicon) // 先加载本地Polyfill view?.loadUrl("file:///android_asset/polyfill.js") } override fun onPageFinished(view: WebView?, url: String?) { super.onPageFinished(view, url) // Polyfill加载完成后再加载目标网站 if (url == "file:///android_asset/polyfill.js") { view?.loadUrl(getString(R.string.url_to_load)) } } }
4. 引导用户更新系统WebView
部分设备的系统WebView内核版本过低,可检测版本并提示用户更新:
val webViewPackage = WebView.getCurrentWebViewPackage() webViewPackage?.let { pkg -> val version = pkg.versionName.split(".").first().toIntOrNull() ?: 0 if (version < 90) { // Chrome 90+对ES6+特性支持完善 AlertDialog.Builder(this) .setTitle("需更新WebView") .setMessage("当前WebView版本过低,无法正常加载页面,请前往应用商店更新Android System WebView") .setPositiveButton("前往更新") { _, _ -> try { startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.google.android.webview"))) } catch (e: ActivityNotFoundException) { startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=com.google.android.webview"))) } } .setCancelable(false) .show() } }
内容的提问来源于stack exchange,提问作者Thomas Cook
相关产品推荐
相关产品推荐

