uniapp 在线升级(热更新)及java后台

        如果你们也是厌倦了每次升级都要重新下载一整个包,重新安装。那么可以试试这个热更新方案,其实热更新这个技术在移动端并不少见,好几年前做原生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包

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

         

 

 加不加混淆看你自己,加了更安全,一定程度上防止反编译

我们可以看到wgt包已经生成了。

 四、java后台编写(只做参考,实际项目自己修改)

 我的后台是个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)

猜你喜欢

转载自blog.csdn.net/qq_30548105/article/details/125551858
今日推荐