Si usted también está cansado de tener que volver a descargar un paquete completo cada vez que actualiza, vuelva a instalarlo. Entonces puede probar esta solución de actualización en caliente. De hecho, la tecnología de actualización en caliente no es poco común en el terminal móvil. Aquellos que hicieron el desarrollo de aplicaciones nativas hace varios años deberían haber estado expuestos a esta tecnología. Esta vez también usé la actualización en caliente de uniapp , así que grábelo, lo cual es conveniente para su uso directo más adelante.
La tecnología no es difícil, mira hacia abajo ~
En primer lugar, creé un proyecto uniapp sin escribir ningún código. Tomemos esto como un proyecto que se ha desarrollado en el proyecto real, después de todo, es solo una demostración. Entonces esta versión se considera como la versión 1.0.0
Ok, entonces, agreguemos código de actualización en caliente a esta versión 1.0.0.
1. Escriba el código de actualización en caliente en la versión anterior
Primero abra el código App.vue en el proyecto y escríbalo en onLaunch, porque esperamos que cuando se inicie la aplicación, detecte si hay una nueva versión que necesita ser actualizada. El código específico es el siguiente:
<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>
El código se te ha dado, pero déjame explicarte. En primer lugar, // #ifdef APP-PLUS no es un comentario, se llama compilación condicional
Compilación condicional (se puede usar en componentes, css, js, configuración .json):
Un bloque de código que será compilado o no ejecutado bajo ciertas condiciones
Sintaxis: // #condicion plataforma
condición:
ifdef: si se define una condición positiva, lo que significa que solo se compilará y tendrá efecto bajo la plataforma xxx
ifndef: si no se define la condición inversa, lo que significa que no tendrá efecto en la plataforma xxx y tendrá efecto en otras plataformas
endif : etiqueta final, significa fin de condición
plataforma:
APP-PLUS solo tendrá efecto en el entorno del lado de la aplicación
APP-PLUS-NVUE solo tendrá efecto en el entorno de la aplicación nvue
H5 solo tendrá efecto en el entorno H5
Miniprograma MP WeChat/Miniprograma Alipay/Miniprograma Baidu/Miniprograma Toutiao/Miniprograma QQ
MP-WEIXIN solo tendrá efecto en el entorno del programa WeChat Mini
MP-ALIPAY solo tendrá efecto en el entorno del subprograma Alipay
MP-BAIDU solo tendrá efecto en el entorno del programa Baidu Mini
MP-TOUTIAO solo tendrá efecto en el entorno del applet ByteDance
MP-360 solo tendrá efecto en el entorno del applet 360
MP-QQ solo tendrá efecto en el entorno del subprograma QQ
plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) es obtener la configuración del programa en sí, y obtener la información del paquete a través de su propio appid
widgetInfo contiene información diversa del paquete, incluido el número de versión y el nombre de la versión
Esta es la configuración, por ejemplo, si somos la versión 1.0.0, el número de versión es 100. Cuando modificamos el error o agregamos una nueva función, podemos cambiar la versión a 1.0.1 y el número de versión a 101. De esta forma, en funcionamiento real, podemos conocer la versión instalada actualmente y comparar las versiones
Más abajo, uni.request es una solicitud normal. Recuerda tu número de versión actual, el que tiene números, no el que tiene puntos. Envíelo al fondo, y el fondo consultará el número de versión de la última versión para comparar.Si la versión enviada es más pequeña que la versión consultada en el fondo, significa que necesita actualizar la versión, y la dirección de descarga ser devuelto Si la versión enviada no es menor que la versión consultada en segundo plano, entonces no hay necesidad de devolver la dirección de descarga, escribí la lógica de esta manera.
Entonces, si juzgo si el código de retorno es 0,0, significa que debe actualizarse y luego descargarlo cuando la dirección de descarga no esté vacía. Después de que la descarga sea exitosa, use plus.runtime.install para instalar
2. Escribe una nueva versión
A continuación, primero escribamos un pequeño código, es decir, en el proyecto real, después de corregir errores o agregar nuevas funciones, se convierte en una nueva versión. Aquí simplemente agrego una línea de código para indicar que se ha agregado una nueva función
Luego ve a manifest.json para modificar la información de la versión.
3. Generar paquete wgt
Generamos el paquete wgt en base a la nueva versión, es decir, el paquete de actualización. Haga clic en liberar para seleccionar el paquete wgt de la aplicación App-make nativo
Depende de usted agregar o no confundir, agregar es más seguro y evita la descompilación hasta cierto punto
Podemos ver que se ha generado el paquete wgt.
4. Escritura en segundo plano de Java (solo como referencia, modifique el proyecto real usted mismo)
Mi fondo es springboot+layui+mybatis
Y solo hice una lista de consultas, cargué el paquete wgt y verifiqué si la función necesita ser actualizada
Estructura de la tabla:
Controlador
@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;
}
}
Servicio
@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;
}
}
Mapeador
@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);
}
Mapeador.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>
El código de la página de inicio no se publicará, es de poca importancia
El diagrama de efecto frontal es el siguiente:
Está bien, cargue este paquete de nueva versión
Efecto después de la actualización:
Bueno, ¡vamos a terminar aquí!
Mi creación personal, si hay alguna similitud es pura coincidencia, o contáctame para hacer cambios. Por favor reimprimir o combinación de CV para indicar la fuente, ¡gracias! (Si tiene alguna pregunta o error, indíquelo, mi QQ: 752231513)