Ionic/Cordova应用升级targetSDK30后闪屏后白屏 WebView缓存错误
近期将Ionic应用的android-targetSDKVersion升级为30后,部分Android 11、Android 12机型出现闪屏页加载完成后持续白屏、无法进入应用的故障。
- 复现范围:三星S20、S21、Pixel 6等实机必现,部分同版本Android设备、全版本Android模拟器可正常运行
- 已尝试无效方案:按照论坛教程禁用后重新启用「Android System WebView」,未解决问题
logcat中抓取到的chromium层报错如下:
2022-07-01 19:54:12.424 17025-17940/? E/chromium: [ERROR:simple_file_enumerator.cc(21)] opendir /data/user/0/com.x.y/cache/WebView/Default/HTTP Cache/Code Cache/wasm: No such file or directory (2)
{ "name": "**", "version": "0.0.1", "author": "***", "homepage": "***", "scripts": { "ng": "ng", "start": "ng serve", "build": "ng build", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" }, "private": true, "dependencies": { "@angular/animations": "^10.0.8", "@angular/common": "^10.0.8", "@angular/core": "^10.0.8", "@angular/forms": "^10.0.8", "@angular/platform-browser": "^10.0.8", "@angular/platform-browser-dynamic": "^10.0.8", "@angular/router": "^10.0.8", "@fortawesome/angular-fontawesome": "0.7.0", "@fortawesome/fontawesome-svg-core": "1.2.30", "@fortawesome/free-solid-svg-icons": "5.14.0", "@ionic-native/camera": "^5.27.0", "@ionic-native/core": "^5.27.0", "@ionic-native/in-app-browser": "^5.27.0", "@ionic-native/keyboard": "^5.27.0", "@ionic-native/open-native-settings": "^5.27.0", "@ionic-native/screen-orientation": "^5.27.0", "@ionic-native/sim": "^5.27.0", "@ionic-native/splash-screen": "^5.27.0", "@ionic-native/status-bar": "^5.27.0", "@ionic/angular": "^5.3.1", "@ionic/cli": "^6.11.0", "@ionic/storage": "^2.3.0", "@ngx-translate/core": "^11.0.1", "@ngx-translate/http-loader": "^4.0.0", "angular2-signaturepad": "^3.0.4", "cordova-android": "9.1.0", "cordova-background-geolocation-lt": "^3.9.2", "cordova-ios": "^5.1.1", "cordova-open-native-settings": "1.5.2", "cordova-plugin-androidx-adapter": "^1.1.3", "cordova-plugin-background-fetch": "^6.1.1", "cordova-plugin-camera": "^4.1.0", "cordova-plugin-device": "^2.0.3", "cordova-plugin-inappbrowser": "^3.2.0", "cordova-plugin-ionic-keyboard": "^2.2.0", "cordova-plugin-ionic-webview": "^4.2.1", "cordova-plugin-screen-orientation": "^3.0.2", "cordova-plugin-sim": "^1.3.3", "cordova-plugin-splashscreen": "^5.0.4", "cordova-plugin-statusbar": "^2.4.3", "cordova-plugin-whitelist": "^1.3.4", "cordova-sqlite-storage": "^3.4.0", "core-js": "^3.6.5", "es6-promise-plugin": "^4.2.2", "hammerjs": "^2.0.8", "rxjs": "^6.6.2", "tslib": "^2.0.0", "zone.js": "~0.10.3" }, "devDependencies": { "@angular-devkit/architect": "^0.803.29", "@angular-devkit/build-angular": "~0.1000.5", "@angular-devkit/core": "^10.0.5", "@angular-devkit/schematics": "^10.0.5", "@angular/cli": "^10.0.5", "@angular/compiler": "^10.0.8", "@angular/compiler-cli": "^10.0.8", "@angular/language-service": "^10.0.8", "@ionic/angular-toolkit": "^2.3.0", "@types/jasmine": "^2.8.17", "@types/jasminewd2": "^2.0.8", "@types/node": "^12.11.1", "codelyzer": "^6.0.0", "cordova-plugin-geolocation": "^4.0.1", "jasmine-core": "~3.5.0", "jasmine-spec-reporter": "~5.0.0", "karma": "~5.0.0", "karma-chrome-launcher": "~3.1.0", "karma-coverage-istanbul-reporter": "~3.0.2", "karma-jasmine": "~3.3.0", "karma-jasmine-html-reporter": "^1.5.0", "protractor": "~7.0.0", "ts-node": "~7.0.0", "tslint": "~6.1.0", "typescript": "~3.9.7" }, "description": "An Ionic project", "cordova": { "plugins": { "cordova-sqlite-storage": {}, "cordova-plugin-sim": {}, "cordova-plugin-whitelist": {}, "cordova-plugin-statusbar": {}, "cordova-plugin-device": {}, "cordova-plugin-splashscreen": {}, "cordova-plugin-ionic-keyboard": {}, "cordova-plugin-camera": {}, "cordova-plugin-geolocation": { "GEOLOCATION_USAGE_DESCRIPTION": "This app has a feature that uses your phone’s Location Services to track you" }, "cordova-open-native-settings": {}, "cordova-plugin-ionic-webview": {}, "cordova-plugin-inappbrowser": {}, "cordova-plugin-screen-orientation": {}, "cordova-background-geolocation-lt": { "BACKGROUND_MODE_LOCATION": "<string>location</string>" }, "cordova-plugin-androidx-adapter": {} }, "platforms": [ "android", "ios" ], "browserslist": [] } }
这个白屏故障和抓到的wasm缓存目录不存在报错直接相关,本质是旧版cordova-plugin-ionic-webview未适配Android 11+的分区存储规则,和重置Android System WebView开关的操作没有关系。
当前项目使用的cordova-plugin-ionic-webview@4.2.1发布时Android 11尚未正式推送,没有做对应存储逻辑适配。WebView启动时需要读取应用缓存下的wasm代码缓存目录,但受分区存储权限限制无法自动创建该路径,直接触发渲染进程崩溃,最终表现为闪屏后持续白屏。不同厂商对系统WebView、存储权限的定制逻辑存在差异,因此会出现同版本安卓系统部分机型可正常运行、三星S20/S21、Pixel 6等机型必现的情况;安卓模拟器默认镜像一般未做严格的存储权限限制,因此也能正常运行。
可按以下步骤修复:
- 移除项目中旧版webview插件,执行命令:
cordova plugin rm cordova-plugin-ionic-webview - 安装已适配Android 11+的5.x稳定版webview插件:
cordova plugin add cordova-plugin-ionic-webview@5.0.0 - 检查项目
config.xml文件,如果存在AndroidInsecureFileModeEnabled的配置项直接删除,5.x版本插件默认已经处理了本地文件访问规则,不需要开启这个存在安全风险的配置。 - 清理构建缓存后重新打包即可:
cordova clean android cordova build android
如果暂时不方便升级webview插件,也可以使用临时补丁方案:找到安卓平台源码下的MainActivity.java文件,在onCreate方法中super.onCreate(savedInstanceState)代码行之前,添加手动创建缺失缓存目录的逻辑。但该方案仅补了当前缺失的wasm缓存路径,后续系统WebView版本升级如果新增其他缓存目录,还是会触发同类问题,优先选择升级插件的方案。
内容的提问来源于stack exchange,提问作者JKRo

