一、要解决的问题:

  实现app内部静默更新。

二、要实现这个功能必须解决以下情况:

  1、app内部如何检测更新了

  2、检测到更新了之后如何获取新的资源下载链接

  3、拿到资源后如何在内部安装

三、操作方式:

  1、首次使用的打包方式uniapp+Android Studio(可以自行去uniapp的官网进行查阅)打包成apk文件,至于不用uniapp打包的原因就是排队太麻烦。

  2、其后更新只需要打包为wgt文件即可在app内部安装

四、具体实现:

  1、首先在后台管理系统定义一个版本、一个资源下载链接和版本更新的内容三个参数

  2、在App.vue中调用接口进行一个版本的比对,如何版本不一致则跳转至更新页进行更新

/**
 * 通过参数设置获取最新版本信息
 */
getVersion() {
    const _this = this;
    uni.$u.api
        .getParameterApi({
	    key: 'parking.operation.version'
        })
	.then(res => {
            if (res.code === 200) {
	        this.version = res.msg
	        if (res.msg !== config.version) {
                   uni.$u.route({
		   url: 'pages/appUpdate/appUpdate',
		   params: {
			downloadUrl: this.downloadUrl, // 和版本一样通过参数获取下载链接
			version: this.version
		   }
		   }) 
                }
            }
  });
}

  3、更新页处理

<template>
  <view class="page-height">
    <view class="page-content">
      <view class="wrap" v-if="popup_show">
        <view class="popup-bg">
          <view class="popup-content" :class="{ 'popup-content-show': popup_show }">
            <view class="update-wrap">
              <image src="/static/images/img.png" class="top-img"></image>
              <view class="content">
                <text class="title">发现新版本V{{ updateInfo.version }}</text>
                <!-- 升级描述 -->
                <view class="title-sub" v-html="updateInfo.note"></view>
                <!-- 操作按钮 -->
                <view class="operation-btn" v-if="downstatus < 1">
                  <button class="btn cancel" @click="cancel()">暂不升级</button>
                  <button class="btn" @click="onUpdate()">立即升级</button>
                </view>
                <!-- 下载进度 -->
                <view class="sche-wrap" v-else>
                  <!-- 更新包下载中 -->
                  <view class="sche-bg">
                    <view class="sche-bg-jindu" :style="lengthWidth"></view>
                  </view>
                  <text class="down-text">下载进度:{{ (downSize / 1024 / 1024).toFixed(2) }}M/{{ (fileSize / 1024 / 1024).toFixed(2) }}M</text>
                </view>
              </view>
            </view>
            <image src="/static/images/close.png" class="close-ioc" @click="closeUpdate()" v-if="downstatus < 1 && updateInfo.force == 0"></image>
          </view>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
import { config } from '@/common/config.js';
export default {
  data() {
    return {
      popup_show: true,
      updateInfo: {
        note: '',
        version: '',
        downloadUrl: ''
      }, //上一页面传过来的升级参数
      note: [], //升级说明数组格式
      fileSize: 0, //文件大小
      downSize: 0, //已下载大小
      downing: false, //是否下载中
      downstatus: 0 //0未下载  1已开始 2已连接到资源  3已接收到数据  4下载完成
    };
  },
  onLoad(option) {
    this.updateInfo.version = option.version;
    this.updateInfo.downloadUrl = option.downloadUrl;
  },
  onBackPress(e) {
    if (e.from == 'backbutton') return true; //APP安卓物理返回键逻辑
  },
  computed: {
    // 下载进度计算
    lengthWidth: function () {
      let w = (this.downSize / this.fileSize) * 100;
      if (!w) {
        w = 0;
      } else {
        w = w.toFixed(2);
      }
      return {
        width: w + '%' //return 宽度半分比
      };
    },
    getHeight: function () {
      let bottom = 0;
      if (this.tabbar) {
        bottom = 50;
      }
      return {
        bottom: bottom + 'px',
        height: 'auto'
      };
    }
  },
  methods: {
    // 当点击更新时
    onUpdate() {
      //判断是否为wifi模式
      uni.getNetworkType({
        success: (res) => {
          if (res.networkType == 'wifi') {
            this.startUpdate(); //开始更新
          } else {
            uni.showModal({
              title: '提示',
              content: '当前网络非WIFI,继续更新可能会产生流量,确认要更新吗?',
              success: (modal_res) => {
                if (modal_res.confirm) {
                  this.startUpdate(); //开始更新
                }
              }
            });
          }
        }
      });
    },
    /**
     * 取消升级
     */
    cancel() {
      uni.$u.route({
        type: 'back',
        delta: 1
      });
    },
    //开始更新
    startUpdate() {
      if (this.downing) return false; //如果正在下载就停止操作
      this.downing = true; //状态改变 正在下载中
      if (/\.wgt$/.test(this.updateInfo.downloadUrl)) {
        // 如果是更新包
        this.download_wgt(); // 安装包/升级包更新
      } else {
        plus.runtime.openURL(this.updateInfo.downloadUrl, function () {
          //调用外部浏览器打开更新地址
          plus.nativeUI.toast('打开错误');
        });
      }
    },
    // 下载升级资源包
    download_wgt() {
      plus.nativeUI.showWaiting('下载更新文件...'); //下载更新文件...
      let options = {
        method: 'get'
      };
      let dtask = plus.downloader.createDownload(this.updateInfo.downloadUrl, options);
      dtask.addEventListener('statechanged', (task, status) => {
        if (status === null) {
        } else if (status == 200) {
          //在这里打印会不停的执行,请注意,正式上线切记不要在这里打印东西!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
          this.downstatus = task.state;
          switch (task.state) {
            case 3: // 已接收到数据
              plus.nativeUI.closeWaiting();
              this.downSize = task.downloadedSize;
              if (task.totalSize) {
                this.fileSize = task.totalSize; //服务器须返回正确的content-length才会有长度
              }
              break;
            case 4:
              this.installWgt(task.filename); // 安装
              break;
          }
        } else {
          plus.nativeUI.closeWaiting();
          plus.nativeUI.toast('下载出错');
          this.downing = false;
          this.downstatus = 0;
        }
      });
      dtask.start();
    },
    // 安装文件
    installWgt(path) {
      plus.nativeUI.showWaiting('安装更新文件...'); //安装更新文件...
      plus.runtime.install(
        path,
        {
          force: true
        },
        function () {
          plus.nativeUI.closeWaiting();
          // 应用资源下载完成!
          plus.nativeUI.alert('更新完成,请重启APP!', function () {
            plus.runtime.restart(); //重启APP
          });
        },
        function (e) {
          plus.nativeUI.closeWaiting();
          // 安装更新文件失败
          plus.nativeUI.alert('安装更新文件失败[' + e.code + ']:' + e.message);
        }
      );
    }
  }
};
</script>

<style lang="scss" scoped>
.page-height {
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background-color: rgba($color: #000000, $alpha: 0.7);
}

.popup-bg {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 750rpx;
}

.popup-content {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.popup-content-show {
  animation: mymove 300ms;
  transform: scale(1);
}

@keyframes mymove {
  0% {
    transform: scale(0);
    /*开始为原始大小*/
  }

  100% {
    transform: scale(1);
  }
}

.update-wrap {
  width: 580rpx;
  border-radius: 18rpx;
  position: relative;
  display: flex;
  flex-direction: column;
  background-color: #ffffff;
  padding: 170rpx 30rpx 0;

  .top-img {
    position: absolute;
    left: 0;
    width: 100%;
    height: 256rpx;
    top: -128rpx;
  }

  .content {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding-bottom: 40rpx;

    .title {
      font-size: 32rpx;
      font-weight: bold;
      color: #6526f3;
    }

    .title-sub {
      text-align: center;
      font-size: 24rpx;
      color: #666666;
      padding: 30rpx 0;
    }
    .operation-btn {
      width: 100%;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }
    .btn {
      width: 200rpx;
      display: flex;
      align-items: center;
      justify-content: center;
      color: #ffffff;
      font-size: 30rpx;
      height: 80rpx;
      line-height: 80rpx;
      border-radius: 100px;
      background-color: #6526f3;
      margin-top: 20rpx;
    }
		.cancel {
			background-color: #cccccc;
			color: #6526f3;
		}
  }
}

.close-ioc {
  width: 70rpx;
  height: 70rpx;
  margin-top: 30rpx;
}

.sche-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  padding: 10rpx 50rpx 0;

  .sche-wrap-text {
    font-size: 24rpx;
    color: #666;
    margin-bottom: 20rpx;
  }

  .sche-bg {
    position: relative;
    background-color: #cccccc;
    height: 30rpx;
    border-radius: 100px;
    width: 480rpx;
    display: flex;
    align-items: center;

    .sche-bg-jindu {
      position: absolute;
      left: 0;
      top: 0;
      height: 30rpx;
      min-width: 40rpx;
      border-radius: 100px;
      background: url(/static/images/round.png) #6526f3 center right 4rpx no-repeat;
      background-size: 26rpx 26rpx;
    }
  }

  .down-text {
    font-size: 24rpx;
    color: #6526f3;
    margin-top: 16rpx;
  }
}
</style>

  4、在manifest.json配置应用安装权限(这两个权限是必须的,否则没有安装应用权限)

"<uses-permission android:name=\"android.permission.INSTALL_PACKAGES\"/>",
"<uses-permission android:name=\"android.permission.REQUEST_INSTALL_PACKAGES\"/>",

  5、这样一个app应用的静默更新就完成了


希望大佬看到有不对的地方,提出博主予以改正!