如果你们也是厌倦了每次升级都要重新下载一整个包,重新安装。那么可以试试这个热更新方案,其实热更新这个技术在移动端并不少见,好几年前做原生APP开发的应该都接触过这个技术,这次我也是用到了uniapp的热更新,所以记录一下,方便后期直接使用。
技术不难,请往下看 ~
首先我是创建了一个uniapp项目,啥代码都没有写。咱们就把这个当做是实际项目中已经开发好的项目,毕竟只是演示嘛。所以这个版本就当做是1.0.0版本吧

好,那么接下来,我们就在这个1.0.0版本中加入热更新的代码吧。
首先打开项目里的App.vue代码,在onLaunch中编写,因为我们希望App一启动的时候就会去检测是否有新版本需要去更新。具体代码如下:
- <script>
- export default {
- onLaunch: function() {
- console.log('App Launch');
- // #ifdef APP-PLUS
- plus.runtime.getProperty(plus.runtime.appid,(widgetInfo)=>{
- console.log(widgetInfo);
- uni.request({
- url:'http://192.168.3.20:8080/UpdateProject/update/check',
- data:{
- versionCode:widgetInfo.versionCode
- },
- success:function(res){
- console.log(res);
- if(res.data.code==0){
- if(res.data.data.down){
- //下载地址根据实际来修改,我这个是拼接前缀的下载地址
- let downUrl="http://192.168.3.20:8080"+res.data.data.down;
- console.log("url:"+downUrl);
- uni.downloadFile({
- url:downUrl,
- success:function(downloadResult){
- if(downloadResult.statusCode==200){
- plus.runtime.install(downloadResult.tempFilePath,{
- force:false
- },function(){
- console.log("安装成功");
- plus.runtime.restart();
- },function(e){
- console.log(e);
- console.log("安装失败...")
- });
- }
- }
- })
- }
- }else{
- console.log("已经是最新版本,无需更新")
- }
- }
- })
- })
- // #endif
- },
- onShow: function() {
- console.log('App Show')
- },
- onHide: function() {
- console.log('App Hide')
- }
- }
- </script>
-
- <style>
- /*每个页面公共css */
- </style>
代码已经给你了,但是听我解说一下哈, 首先,// #ifdef APP-PLUS 这个玩意不是个注释,这叫条件编译
条件编译(在组件,css,js , .json配置中都可以使用):
在某种条件下才会编译执行或者不执行的代码块
语法: // #条件 平台
条件:
ifdef : if defined 正向条件,意思就是在xxx平台下才会编译生效
ifndef : if not defined 反向条件,意思就是在xxx平台下不会生效,其他平台都生效
endif : 结束标记,意味着条件结束
平台:
APP-PLUS 只会在app端环境下生效
APP-PLUS-NVUE 只会在app nvue环境下生效
H5 只会在H5环境下生效
MP 微信小程序/支付宝小程序/百度小程序/头条小程序/QQ小程序
MP-WEIXIN 只会在微信小程序环境下生效
MP-ALIPAY 只会在支付宝小程序环境下生效
MP-BAIDU 只会在百度小程序环境下生效
MP-TOUTIAO 只会在字节跳动小程序环境下生效
MP-360 只会在360小程序环境下生效
MP-QQ 只会在QQ小程序环境下生效
plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) 就是获取程序自身配置,通过自身的appid获取程序包信息
widgetInfo 里面就包含了各种包信息,其中就有版本号,版本名称
就是这个配置,比如我们是1.0.0版本,版本号就是100,等我们修改了bug或者新增了功能,版本我们就可以改成1.0.1,版本号就改成101。这样实际运营时,我们就可以知道目前安装的版本是多少,以及进行版本比较了

再往下uni.request就是个正常的请求,把自己当前的版本号,记得是数字的那个,不是那个带点的。发给后台,后台去查询最新的版本的版本号进行比较,如果发送的版本小于后台查询的版本,那么说明你需要更新版本了,会返回下载地址等,如果发送的版本不小于后台查询的版本,那么就无需返回下载地址,我是这样写的逻辑。
所以我判断返回code是否是0,0的话,代表需要更新,然后当下载地址不为空时就去下载了。下载成功后,就使用plus.runtime.install去安装即可
接下来我们先编写一点代码,也就是实际项目中,我们修复了bug或者新增了功能之后,变成了新的版本。我这里就是简单加行代码表示新增了功能

然后要去manifest.json中修改版本信息

我们基于新版本生成wgt包,也就是升级包。点击发行选择 原生App-制作应用wgt包

加不加混淆看你自己,加了更安全,一定程度上防止反编译
![]()
我们可以看到wgt包已经生成了。
我的后台是个springboot+layui+mybatis
而且我只做了查询列表,上传wgt包,跟检查是否需要更新功能
表结构:
Controller
- @RestController
- @RequestMapping("/update")
- public class UpdateController {
-
- //tomcat虚拟路径,上传的wgt存放在这里,实际项目中存放在ftp服务器,或者oss上
- @Value("${upload.filePath}")
- private String filePath;
-
- @Autowired
- private UpdateService updateService;
-
- /**
- * 分页查询App版本列表
- * @param page 页码
- * @param limit 每页大小
- * @return 分页后的版本列表数据
- */
- @RequestMapping("/list")
- public ResultTableBean getListByPage(int page,int limit){
- ResultTableBean rtb=new ResultTableBean();
- List<UpdateBean> list = updateService.findUpdateBeanList(page, limit);
- int updateCount = updateService.getUpdateCount();
- rtb.setCode(0);
- rtb.setData(list);
- rtb.setCount(updateCount);
- return rtb;
- }
-
- /**
- * 检查是否需要更新
- * @param versionCode 版本号
- * @return 结果
- */
- @RequestMapping("/check")
- public ResultBean checkAppNeedUpdate(int versionCode){
- ResultBean rb=new ResultBean();
- UpdateBean updateBean = updateService.checkUpdate(versionCode);
- if (updateBean!=null){
- rb.setCode(0);
- rb.setData(updateBean);
- }else {
- rb.setCode(1);
- }
- return rb;
- }
-
- @RequestMapping("/add")
- public ResultBean uploadAppVersion(@RequestParam("app") MultipartFile file, UpdateBean bean){
- ResultBean rb=new ResultBean();
- //获取文件名
- String originalFilename = file.getOriginalFilename();
- //获取文件的后缀名
- String suffixName = originalFilename.substring(originalFilename.lastIndexOf("."));
- //为了避免同一个文件夹下文件名重复问题,所以随机生成uuid作为文件名
- String fileName= UUID.randomUUID()+suffixName;
- File file1=new File(filePath+fileName);
- try {
- //文件存放到虚拟路径下
- file.transferTo(file1);
- //保存虚拟路径到数据库
- bean.setDown("/appVersion/"+fileName);
- boolean result = updateService.addUpdateBean(bean);
- if (result) {
- rb.setCode(0);
- }else {
- rb.setCode(1);
- }
- } catch (IOException e) {
- e.printStackTrace();
- rb.setCode(2);
- }
- return rb;
- }
-
- }
Service
- @Service
- public class UpdateServiceImpl implements UpdateService {
-
- @Autowired
- private UpdateMapper updateMapper;
-
- @Override
- public List<UpdateBean> findUpdateBeanList(int page, int limit) {
- return updateMapper.findUpdateBeanList((page-1)*limit,limit);
- }
-
- @Override
- public int getUpdateCount() {
- return updateMapper.getUpdateCount();
- }
-
-
- @Override
- public boolean addUpdateBean(UpdateBean bean) {
- int row = updateMapper.addUpdateBean(bean);
- if(row>0){
- return true;
- }
- return false;
- }
-
- @Override
- public UpdateBean checkUpdate(int versionCode) {
- UpdateBean updateBeanLast = updateMapper.findUpdateBeanLast();
- if (updateBeanLast!=null){
- if (updateBeanLast.getCode()>versionCode){
- return updateBeanLast;
- }
- }
- return null;
- }
- }
Mapper
- @Repository
- @Mapper
- public interface UpdateMapper {
-
- /**
- * 分页查询版本列表
- * @param start 起始位置
- * @param end 结束位置
- * @return 版本列表
- */
- public List<UpdateBean> findUpdateBeanList(int start,int end);
-
- /**
- * 获取版本列表总个数
- * @return 总个数
- */
- public int getUpdateCount();
-
- /**
- * 查询最新的版本
- * @return 最新的版本
- */
- public UpdateBean findUpdateBeanLast();
-
- /**
- * 新增APP版本
- * @param bean 版本信息
- * @return 受影响的行数
- */
- public int addUpdateBean(UpdateBean bean);
- }
Mapper.xml
- <select id="findUpdateBeanList" resultType="com.xxx.update.bean.UpdateBean">
- select *from tb_update order by upload_time desc limit #{param1},#{param2}
- </select>
-
- <select id="getUpdateCount" resultType="int">
- select count(*) from tb_update
- </select>
-
- <select id="findUpdateBeanLast" resultType="com.xxx.update.bean.UpdateBean">
- select *from tb_update order by upload_time desc limit 1
- </select>
-
- <insert id="addUpdateBean" parameterType="com.xxx.update.bean.UpdateBean">
- insert into tb_update values(null,#{name},#{code},#{desc},#{down},now())
- </insert>
前端页面代码就不放了,意义不大
前端效果图如下:

这样就OK了,上传了这个新版本包
升级后效果:

好了,到此就告一段落吧!
本人个人原创,如有雷同,纯属巧合,或者与本人联系,做改动。请转载或者CV组合标明出处,谢谢!(如有疑问或错误欢迎指出,本人QQ:752231513)