师大酸梅杨
师大酸梅杨
  • 发布:2025-08-05 17:12
  • 更新:2025-08-19 15:24
  • 阅读:223

uniapp Android离线打包,覆盖安装后,界面回到上一版本的问题

分类:uni-app

Uniapp离线打包App覆盖安装后界面回退问题分析与解决

问题描述

  • 环境信息
    • 开发框架:Uniapp
    • 硬件平台:RK3568开发板
    • 系统版本:Android 11
    • 打包方式:离线打包
  • 现象
    • 覆盖安装新版本后,偶现界面显示为上一个版本
    • 重启应用后恢复正常(显示最新版本界面)
    • 问题出现概率难统计,有时需要设备断电重启,有时设备软重启也会出现

可能原因分析

1. 资源缓存问题

  • Android AssetManager缓存机制
  • Uniapp资源热更新机制冲突

2. 安装流程时序问题

  • APK安装完成但资源未完全解压
  • RK3568芯片组特定处理逻辑

3. WebView缓存问题

  • Uniapp基于WebView的渲染机制
  • 旧版本缓存未被及时清除

排查过程

  1. 日志分析

    • 增加安装完成回调日志
    • 监控WebView初始化过程
  2. 测试对比

    • 不同Android版本设备对比测试
    • 相同代码在不同主板的表现
  3. 关键发现

    • 问题仅出现在RK3568这款主板上
    • 安装启动后,在 /data/data/${packageName}/ 目录下,发现了一个apps文件夹,该文件夹下,居然包含了离线打包的资源文件;
    • 正常启动过程,资源文件应在 /data/data/${packageName}/files 目录下。同时查看该目录,也发现了离线打包的资源文件;
    • 分别打开两个目录下,资源文件里的manifest.json 文件,对比versionCode 和versionName,豁然开朗。

正常目录:

异常目录:

可能原因分析

1. 主板固件问题

  • Android固件为厂商定制,存在Bug。测试方式,使用纯原生应用,检测验证;

    2. uniapp框架Bug;

  • 个人感觉可能性非常大。此处仅为技术方面探讨,不存在抹黑、针对任何方。😅

解决方案

临时解决方案

  • 要从根本原因这两方面入手解决都比较困难。知道了原因,就好针对性的解决了。
    每次启动的时候,检测异常目录下,是否存在manifest.json文件,如存在则尝试解析其中的versionCode和versionName。不管是否一致,都应删除掉异常目录下的所有文件,然后重启应用。主要示例代码如下:

    private fun checkAndCleanLegacyResources() {  
        try {  
            // 获取应用私有目录  
            val datasDir = applicationContext.dataDir  
    
            TARGET_FOLDER_NAME=BaseInfo.sDefaultBootApp  
            // 构建目标目录路径  
            val targetDir = File(datasDir, "apps/$TARGET_FOLDER_NAME")  
    
            // 检查目标目录是否存在  
            if (!targetDir.exists() || !targetDir.isDirectory) {  
                ToastUtils.show("ResourceCleaner 目标目录不存在: " + targetDir.absolutePath)  
                return  
            }  
    
            // 检查 manifest 文件是否存在  
            val manifestFile = File(targetDir, MANIFEST_PATH)  
            if (!manifestFile.exists()) {  
                ToastUtils.show("ResourceCleaner manifest.json 文件不存在")  
                return  
            }  
    
            // 解析 manifest 文件中的版本信息  
            val legacyVersion = parseManifestVersion(manifestFile)  
            if (legacyVersion == null) {  
                ToastUtils.show("ResourceCleaner 无法解析版本信息")  
                return  
            }  
    
            // 获取当前应用版本  
            val currentVersion = getCurrentAppVersion()  
    
            // 比较版本并决定是否删除  
            if (shouldDeleteLegacyResources(legacyVersion, currentVersion)) {  
                ToastUtils.show("ResourceCleaner 发现旧版本资源: $legacyVersion (当前版本: $currentVersion)")  
                deleteRecursive(targetDir)  
                ToastUtils.show("ResourceCleaner 已成功删除旧资源")  
            } else {  
                ToastUtils.show("ResourceCleaner 资源版本是最新的: $legacyVersion")  
            }  
        } catch (e: Exception) {  
            ToastUtils.show("ResourceCleaner 清理资源时出错: " + e.message)  
        }  
    }  
    private fun deleteRecursive(fileOrDirectory: File) {  
        if (fileOrDirectory.isDirectory) {  
            val children = fileOrDirectory.listFiles()  
            if (children != null) {  
                for (child in children) {  
                    deleteRecursive(child)  
                }  
            }  
        }  
        fileOrDirectory.delete()  
    }

    看下效果

应用重启后,旧版资源文件已经被删除了,重启几次,持续观察了几天,也没有出现回退的情况。

尽管方案不太完美,用户体验略差,期待官方重视,或者大家有更好的解决办法,一起交流下吧。

0 关注 分享

要回复文章请先登录注册

unicorn_up

unicorn_up

uniapp打包的apk,在rk3568设备下很多小问题。
2025-08-19 15:24