前言
RK平台上,封装的原生Android SDK给客户Uniapp嵌入调用,给安装的Uniapp设置开机自启动,因为使用环境的限制,更新Uniapp时,不能卸载,不能清除App缓存,只能通过U盘覆盖安装。但是当更新版本后,设备开机自启动跳转了旧版本的主页。
问题分析
此问题分析怀疑可能是以下两点原因:
1、RK平台上自启动模式机制有问题,第一次设置App开机自启,可能是将App的路径和hash值写入到了某些脚本,Uniapp更新时候,无法将其安装覆盖,脚本里调用的是安装时生成的固定路径(或者旧的安装路径 hash)。
2、是Uniapp打包方式或运行框架机制,UniApp 的 Android 应用本质上是一个 壳 app (wrapper),里面通过一个 WebView + JS 引擎 加载你的业务逻辑,当通过 U 盘覆盖安装时,系统确实替换了新的 base.apk,但 uniapp 的离线资源、自启动注册信息仍然在以下路径。
            
            
              powershell
              
              
            
          
          /data/data/com.xxx.xxx/apps/__UNI__xxxxxx/
        而这个路径不会被覆盖更新!所以仍然加载旧的配置和启动逻辑。
问题验证
分析完需求后,逐步验证上述猜想。
猜想1:
1、安装新版本UniApp后,查看旧版本是否还存在。

检查/data/app目录下,查看旧版本的Uniapp已经不存在了,说明已经覆盖安装。
2、使用原生测试App验证是否和Uniapp情况一致
原生Android编写测试代码,打成TestApk1和TestApk2,两个Apk页面内容做区分,先安装TestApk1,设置开机自启动。再使用U盘安装TestApk2后重启,发现现象是正常的,和Uniapp有差异
猜想2:
查看Uniapp安装应用数据目录

UniApp在安装时会解压资源文件到/data/data/com.xxx.xxx/apps/__UNI__4992AC7/目录
            
            
              powershell
              
              
            
          
          # 清理UniApp相关目录
rm -rf /data/data/com.xxx.xxx/apps/__UNI__4992AC7/*
rm -rf /data/data/com.xxx.xxx/apps/.md5
rm -rf /data/data/com.xxx.xxx/files/.md5
rm -rf /data/data/com.xxx.xxx/cache/*
rm -rf /data/data/com.xxx.xxx/code_cache/*
        尝试使用上述指令清除缓存,执行完毕后,安装新版本Uniapp,发现设备重启后,自启动打开的是新版本页面,问题的原因就找到了。
制作Android App
为了方便客户操作,需要开发App,点击按钮后就能完成清除Uniapp缓存,实现和adb指令一样的效果。因为有系统签名,不需要权限申请等操作,这里只贴出清除资源文件的代码。
            
            
              kotlin
              
              
            
          
              private const val TARGET_PACKAGE = "com.xxx.xxx"
    private fun executeCleanCommands(): Boolean {
        return try {
            val process = Runtime.getRuntime().exec("su")
            val outputStream = DataOutputStream(process.outputStream)
            val appDataDir = "/data/data/$TARGET_PACKAGE"
            // 1. 停止应用
            Log.d(TAG, "停止应用...")
            outputStream.writeBytes("am force-stop $TARGET_PACKAGE\n")
            outputStream.flush()
            Thread.sleep(2000)
            // 2. 只清理UniApp的www资源目录,保留其他文件
            Log.d(TAG, "清理UniApp资源...")
            // 清理所有UniApp目录中的www文件夹内容(这是UniApp的主要资源目录)
            outputStream.writeBytes("find $appDataDir/apps/__UNI__*/www -type f -delete 2>/dev/null\n")
            outputStream.flush()
            // 清理js文件缓存
            outputStream.writeBytes("find $appDataDir/apps/__UNI__*/js -type f -delete 2>/dev/null\n")
            outputStream.flush()
            // 清理css文件缓存
            outputStream.writeBytes("find $appDataDir/apps/__UNI__*/css -type f -delete 2>/dev/null\n")
            outputStream.flush()
            // 清理静态资源缓存
            outputStream.writeBytes("find $appDataDir/apps/__UNI__*/static -type f -delete 2>/dev/null\n")
            outputStream.flush()
            // 3. 清理特定的缓存文件,但不删除数据库和配置
            Log.d(TAG, "清理特定缓存...")
            val safeCleanCommands = listOf(
                // 只清理apps目录下的缓存文件,不清理整个目录
                "rm -f $appDataDir/apps/.md5 2>/dev/null",
                "rm -f $appDataDir/files/.md5 2>/dev/null",
                // 清理系统缓存目录,但不影响数据库
                "rm -rf $appDataDir/cache/* 2>/dev/null",
                "rm -rf $appDataDir/code_cache/* 2>/dev/null",
                // 清理WebView缓存
                "rm -rf $appDataDir/app_webview/* 2>/dev/null",
                // 特别注意:不删除这些目录,只清理特定缓存文件
                "# 保留数据库: $appDataDir/databases/",
                "# 保留配置: $appDataDir/shared_prefs/"
            )
            safeCleanCommands.forEach { command ->
                if (!command.startsWith("#")) {
                    outputStream.writeBytes("$command\n")
                    outputStream.flush()
                }
            }
            Log.d(TAG, "执行温和缓存清理...")
            outputStream.writeBytes("pm trim-caches $TARGET_PACKAGE 2>/dev/null\n")
            outputStream.flush()
            // 5. 修复权限
            Log.d(TAG, "修复权限...")
            outputStream.writeBytes("chmod -R 755 $appDataDir 2>/dev/null\n")
            outputStream.flush()
            outputStream.writeBytes("exit\n")
            outputStream.flush()
            val result = process.waitFor()
            Log.d(TAG, "精确清理完成,退出码: $result")
            result == 0
        } catch (e: Exception) {
            Log.e(TAG, "执行精确清理命令失败", e)
            false
        }
    }
        上述指令用于查找和清除Uniapp的旧的Web资源文件,新版本安装后生成新的资源文件,这样就能彻底解决这个问题。
            
            
              powershell
              
              
            
          
          find $appDataDir/apps/__UNI__*/www -type f -delete 2>/dev/null
        在UniApp的 www 目录中,通常会包含:
            
            
              php
              
              
            
          
          www/
├── index.html          # 主页面文件
├── css/
│   ├── app.css         # 样式文件
│   └── chunk-*.css     # 代码块样式
├── js/
│   ├── app.js          # 主应用逻辑
│   ├── chunk-*.js      # 代码块文件
│   └── runtime.js      # 运行时文件
├── static/
│   ├── images/         # 图片资源
│   ├── fonts/          # 字体文件
│   └── icons/          # 图标文件
└── manifest.json       # 应用配置
        
总结
~