uniapp 实现APP强更新,热更新

这里我封装了一个版本更新的组件

 

 

 项目版本号在manifest.json---基础配置中查看

 应用版本名称     2.1.07  这种三段式的就是大版本号,一般用于版本强制更新,比如重新安装apk包

应用版本号         2107    就是小版本号 ,一般用于热更新  

 

下面是代码

首先在项目入口地址App.vue 界面获取设备信息,版本号信息,保存下来

	onLaunch: function() {
          // 获取手机设备信息 const res = uni.getSystemInfoSync(); uni.setStorageSync('platform', res.platform); // #ifdef APP-PLUS
          // 获取应用版本信息 plus.runtime.getProperty(plus.runtime.appid, function(inf) { uni.setStorageSync('version', inf.version); // 大版本号 uni.setStorageSync('versionCode', inf.versionCode); // 小版本号 }); let uuid = plus.device.uuid; // #endif },

 下面是强更新,热更新代码

  这里是我写成了一个下载更新的组件    downloadUp.vue,   组件放在项目首页,如果版本需要更新,就会唤起组件弹窗,让用户手动强制更新,热更新的话,进入首页就自动触发了

	created() {
          // 获取设备是安卓还是ios const appUpdate = uni.getStorageSync('platform'); // #ifdef APP-PLUS   this.type = appUpdate == 'android' ? 2 : 1;   this.checkUpdate(); // 判断是否需要更新 // #endif },

  

        checkUpdate() {
            const self = this,
                localAppVersonName = uni.getStorageSync('version'),
                localAppVerson = uni.getStorageSync('versionCode');
                
            // #ifdef APP-PLUS
            plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) {
                getUpgrade({
                    appType: self.type
                }).then(res => {
                    const { data } = res.data;
                    if (res.data.code !== '200') return;
                    // app大版本更新
                    if (data.apkVersion && comparisonVersionHandler(localAppVersonName, data.apkVersion.appVersonName)) {
                        uni.hideTabBar()    // 隐藏首页底部tabbar 按钮
                        self.updateApkObj = data.apkVersion;
                        self.msg = data.apkVersion.versonLog;
                        self.bannerShow = true;  // 显示弹窗
                        return;
                    // app热更新
                    } else if (data.wgtVersion && comparisonVersionHandler(localAppVerson, data.wgtVersion.appVerson)) {
                        self.downloadWgt(data.wgtVersion.downloadUrl);
                        return;
                    } else {
                        return;
                    }
                });
            });
            // #endif
        },
comparisonVersionHandler 是判断版本号是否需要更新的方法
    comparisonVersionHandler = (reqV, curV) => {
    /* 版本号名比较是否需要升级
    curV string :当前最新
    reqV string :之前
    
    返回 true 表示需要升级
    */
    if (curV && reqV) {
        curV = String(curV);
        reqV = String(reqV);
        //将两个版本号拆成数字
        let arr1 = curV.split('.'), //當前
            arr2 = reqV.split('.');
        let minLength = Math.min(arr1.length, arr2.length),
            position = 0,
            diff = 0;
        //依次比较版本号每一位大小,当对比得出结果后跳出循环
        while (position < minLength && ((diff = parseInt(arr1[position]) - parseInt(arr2[position])) == 0)) {
            position++;
        }
        diff = (diff != 0) ? diff : (arr1.length - arr2.length);
        //若curV大于reqV,则返回true
        return diff > 0;
    } else {
        //输入为空
        return false;
    }
};
代码热更新
downloadWgt(updateWgtUrl) {
			// 热更新
			// 下载wgt方法
			const that = this;
			// 更新文件 wgt 文件地址
			plus.nativeUI.showWaiting('正在更新...'); // 打开系统等待对话框
			plus.downloader
				.createDownload(
					updateWgtUrl,
					{
						filename: '_doc/update/'
					},
					function(d, status) {
						if (status == 200) {
							that.installWgt(d.filename); 
						}
						plus.nativeUI.closeWaiting();   // 关闭系统等待对话框

                        }
                     )
                     .start();
},

  installWgt(path) {
    // 安装wgt方法
    plus.nativeUI.showWaiting('安装文件...');
    plus.runtime.install(
      path,
      { force: true },
      function() {
        plus.nativeUI.closeWaiting();
        plus.nativeUI.alert('应用资源更新完成!', function() {
          plus.runtime.restart();  // 重启APP
        });
      },
      function(e) {
        plus.nativeUI.closeWaiting();
      }
    );
  },

 

 強更新

		goUpdate(updateApkObj) {
			if (this.type == 2) { // 安卓端
				// 弹出系统等待对话框
				var dtask = plus.downloader.createDownload(updateApkObj.downloadUrl, {}, function(d, status) {
					this.bannerShow = false;
					// 下载完成
					if (status == 200) {
						plus.runtime.install(plus.io.convertLocalFileSystemURL(d.filename), {}, {}, function(error) {
							uni.showToast({
								title: '安装失败',
								mask: false,
								duration: 1500
							});
						});
					} else {
						uni.showToast({
							title: '更新失败',
							mask: false,
							duration: 1500
						});
					}
				});
				try {
					dtask.start(); // 开启下载的任务
					let prg = 0;
					const showLoading = plus.nativeUI.showWaiting('正在下载'); //创建一个showWaiting对象
					dtask.addEventListener('statechanged', function(task, status) {
						// 给下载任务设置一个监听 并根据状态  做操作
						switch (task.state) {
							case 1:
								showLoading.setTitle('正在下载');
								break;
							case 2:
								showLoading.setTitle('已连接到服务器');
								break;
							case 3:
								prg = parseInt((parseFloat(task.downloadedSize) / parseFloat(task.totalSize)) * 100);
								showLoading.setTitle('  正在下载' + prg + '%  ');
								break;
							case 4:
								plus.nativeUI.closeWaiting();
								//下载完成
								break;
						}
					});
				} catch (err) {
					plus.nativeUI.closeWaiting();
					uni.showToast({
						title: '更新失败-03',
						mask: false,
						duration: 1500
					});
				}
			} else if (this.type == 1) {  // ios跳转到app store
				plus.runtime.openURL(updateApkObj.downloadUrl);
			}
		}

  下面是全部代碼

<template>
    <view class="content" v-if="bannerShow">
        <!-- 弹出层 -->
        <view class="uni-banner">
            <image src="/static/img/startUpHeader01.png" class="startUpHeaderLogo" />
            <view class="banner_box">
                <view class="startUpHeaderBox h6">发现新版本</view>
                <view class="conter">{{ msg }}</view>
                <view class="banner_foot"><button @click="goUpdate(updateApkObj)" class="banner_foot_button">前往升级</button></view>
            </view>
        </view>
        <view class="uni-mask"></view>
    </view>
</template>
<script>
import { comparisonVersionHandler } from '@/common/js/tools';
import { getUpgrade } from '@/common/js/apis';

export default {
    data() {
        return {
            bannerShow: false, // 是否需要強制更新app
            msg: '',  // 更新描述
            type: '', // 设备类型  android:2, ios:1
            updateApkObj: null // 后台数据
        };
    },
    created() {
        const appUpdate = uni.getStorageSync('platform');
        // #ifdef APP-PLUS
        this.type = appUpdate == 'android' ? 2 : 1;
        this.checkUpdate();
        // #endif
        
    },
    methods: {
        checkUpdate() {
            const self = this,
                localAppVersonName = uni.getStorageSync('version'),
                localAppVerson = uni.getStorageSync('versionCode');
                
            // #ifdef APP-PLUS
            plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) {
                getUpgrade({
                    appType: self.type
                }).then(res => {
                    const { data } = res.data;
                    if (res.data.code !== '200') return;
                    // 大版本更新
                    if (data.apkVersion && comparisonVersionHandler(localAppVersonName, data.apkVersion.appVersonName)) {
                        uni.hideTabBar()
                        self.updateApkObj = data.apkVersion;
                        self.msg = data.apkVersion.versonLog;
                        self.bannerShow = true;
                        return;
                    // app热更新
                    } else if (data.wgtVersion && comparisonVersionHandler(localAppVerson, data.wgtVersion.appVerson)) {
                        self.downloadWgt(data.wgtVersion.downloadUrl);
                        return;
                    } else {
                        return;
                    }
                });
            });
            // #endif
        },
        downloadWgt(updateWgtUrl) {
            // 热更新
            // 下载wgt方法
            const that = this;
            // 更新文件 wgt 文件地址
            plus.nativeUI.showWaiting('正在更新...');
            plus.downloader
                .createDownload(
                    updateWgtUrl,
                    {
                        filename: '_doc/update/'
                    },
                    function(d, status) {
                        if (status == 200) {
                            that.installWgt(d.filename); // 安装wgt方法
                        }
                        plus.nativeUI.closeWaiting();
                    }
                )
                .start();
        },
        installWgt(path) {
            // 安装wgt方法
            plus.nativeUI.showWaiting('安装文件...');
            plus.runtime.install(
                path,
                { force: true },
                function() {
                    plus.nativeUI.closeWaiting();
                    plus.nativeUI.alert('应用资源更新完成!', function() {
                        plus.runtime.restart();
                    });
                },
                function(e) {
                    plus.nativeUI.closeWaiting();
                }
            );
        },
        goUpdate(updateApkObj) {
            if (this.type == 2) {
                // 弹出系统等待对话框
                var dtask = plus.downloader.createDownload(updateApkObj.downloadUrl, {}, function(d, status) {
                    this.bannerShow = false;
                    // 下载完成
                    if (status == 200) {
                        plus.runtime.install(plus.io.convertLocalFileSystemURL(d.filename), {}, {}, function(error) {
                            uni.showToast({
                                title: '安装失败',
                                mask: false,
                                duration: 1500
                            });
                        });
                    } else {
                        uni.showToast({
                            title: '更新失败',
                            mask: false,
                            duration: 1500
                        });
                    }
                });
                try {
                    dtask.start(); // 开启下载的任务
                    let prg = 0;
                    const showLoading = plus.nativeUI.showWaiting('正在下载'); //创建一个showWaiting对象
                    dtask.addEventListener('statechanged', function(task, status) {
                        // 给下载任务设置一个监听 并根据状态  做操作
                        switch (task.state) {
                            case 1:
                                showLoading.setTitle('正在下载');
                                break;
                            case 2:
                                showLoading.setTitle('已连接到服务器');
                                break;
                            case 3:
                                prg = parseInt((parseFloat(task.downloadedSize) / parseFloat(task.totalSize)) * 100);
                                showLoading.setTitle('  正在下载' + prg + '%  ');
                                break;
                            case 4:
                                plus.nativeUI.closeWaiting();
                                //下载完成
                                break;
                        }
                    });
                } catch (err) {
                    plus.nativeUI.closeWaiting();
                    uni.showToast({
                        title: '更新失败-03',
                        mask: false,
                        duration: 1500
                    });
                }
            } else if (this.type == 1) {  // ios跳转到app store
                plus.runtime.openURL(updateApkObj.downloadUrl);
            }
        }
    }
};
</script>

<style lang="scss" scoped>
.content,
#img {
    width: 100%;
    height: 100%;
}

.content .con {
    font-size: 0;
    display: flex;
    align-items: center;
}


#info {
    position: absolute;
    top: 0;
    left: 0;
    width: 72rpx;
    height: 72rpx;
    line-height: 72rpx;
    border-radius: 50%;
    background-color: rgba(0, 0, 0, 0.3);
    text-align: center;
    color: #fff;
    font-size: 24rpx;
}


.wrapper {
    width: 36rpx;
    height: 72rpx;
    position: absolute;
    top: 0;
    overflow: hidden;
}

.right {
    right: 0;
}

.left {
    left: 0;
}







/* 弹出层形式的广告 */
.uni-banner {
    display: flex;
    align-items: center;
    flex-direction: column;
    position: fixed;
    left: 50%;
    top: 50%;
    z-index: 1000;
    transform: translate(-50%, -50%);
    width: 80%;

    .startUpHeaderLogo {
        width: 256rpx;
        height: 194rpx;
    }

    .banner_box {
        width: 100%;
        background: #fff;
        border-radius: 20rpx;
    }

    .startUpHeaderBox {
        width: 100%;
        height: 96rpx;
        background-image: url('/static/img/startUpHeader02.png');
        background-position: left top;
        background-repeat: no-repeat;
        background-size: cover;
    }
}

.banner_box .h6 {
    text-align: center;
    line-height: 96rpx;
    font-size: 36rpx;
    color: #fff;
    font-weight: bold;
}

.banner_box .conter {
    font-size: 28rpx;
    color: #333;
    margin: 48rpx;
}

.banner_foot {
    width: 238rpx;
    margin: 48rpx auto;
}

.banner_foot_button {
    background-image: linear-gradient(to right, #3aaf7a, #41bf7f);
    line-height: 72rpx;
    height: 72rpx;
    font-size: 30rpx;
    color: #fff;
    font-weight: bold;
    border-radius: 40rpx;
    border: none;
    box-shadow: 0 8rpx 20rpx 0 rgba(46, 189, 88, 0.36);
}

.banner_foot_button:active {
    background-image: linear-gradient(to right, #41bf7f, #3aaf7a);
}

.uni-mask {
    background: rgba(0, 0, 0, 0.6);
    position: fixed;
    width: 100%;
    height: 100%;
    left: 0;
    top: 0;
    z-index: 2;
}
</style>

 

posted @ 2023-03-04 09:38  live丶  阅读(2481)  评论(0编辑  收藏  举报