新的需求出来啦,需要自动更新功能,不怕程序升级了。

自动更新,QML不好写,需要c++来辅助,这里就涉及QML中调用c++功能(这里就不写了,百度一下,很多)。

思路:获取版本》下载程序》安装程序

第一步,获取版本信息,可以通过XMLHttpRequest获取最新版本。

第二步,下载程序,通过Qt c++的QtNetwork:

头文件:

 #ifndef ZRDOWNLOAD_H
#define ZRDOWNLOAD_H #include <QObject>
#include <QtNetwork/QNetworkAccessManager>
#include <QFile>
#include <QtNetwork/QNetworkReply>
#include <QtNetwork/QNetworkRequest>
#include <QIODevice> class ZRDownload : public QObject
{
Q_OBJECT
Q_PROPERTY(QString url READ GetUrl WRITE SetUrl)
Q_PROPERTY(QString fileName READ GetFileName WRITE SetFileName)
public:
explicit ZRDownload(QObject *parent = );
~ZRDownload(); QString GetUrl();
void SetUrl(QString u);
QString GetFileName();
void SetFileName(QString fn);
private:
QString url;
QString fileName;
QFile *file;
QNetworkAccessManager *accessManager;
QNetworkRequest request;
QNetworkReply *reply; signals:
void progressPosition(double pre); //更新进度条信号
void downloadFinished(); //结束信号 protected slots:
void httpDownload();
void replyFinished(QNetworkReply*reply);
void onDownloadProgress(qint64 bytesSent,qint64 bytesTotal);
void onReadyRead();
}; #endif // ZRDOWNLOAD_H

CPP文件:

#include "zrdownload.h"
#include <QDebug> ZRDownload::ZRDownload(QObject *parent) : QObject(parent)
{
accessManager = NULL;
reply = NULL;
}
ZRDownload::~ZRDownload()
{
} QString ZRDownload::GetUrl()
{
return url;
} void ZRDownload::SetUrl(QString u)
{
url = u;
} QString ZRDownload::GetFileName()
{
return fileName;
} void ZRDownload::SetFileName(QString fn)
{
fileName = fn;
} void ZRDownload::httpDownload(){ file=new QFile(fileName);
bool suc = file->open(QIODevice::WriteOnly);//只读方式打开文件 accessManager=new QNetworkAccessManager(this); request.setUrl(url); /******************设置http的header***********************/
// request.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data");
// request.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream");
// request.setRawHeader("Content-Disposition","form-data;name='doc';filename='a.txt'");
//request.setHeader(QNetworkRequest::ContentLengthHeader,post_data.length()); reply=accessManager->get(request);//通过发送数据,返回值保存在reply指针里.
connect(accessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));//finish为manager自带的信号,replyFinished是自定义的
connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT( onDownloadProgress(qint64 ,qint64 )));//download文件时进度
connect((QObject *)reply, SIGNAL(readyRead()),this, SLOT(onReadyRead())); }
/***************响应结束**************************/
void ZRDownload::replyFinished(QNetworkReply *reply){
//获取响应的信息,状态码为200表示正常
QVariant status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
QByteArray bytes = reply->readAll(); //获取字节
QString result(bytes); //转化为字符串 //无错误返回
if(reply->error() == QNetworkReply::NoError)
{
QByteArray bytes = reply->readAll(); //获取字节
QString result(bytes); //转化为字符串 file->flush();
file->close();
delete file;
file=NULL;
}
else
{
//处理错误
} reply->deleteLater();//要删除reply,但是不能在repyfinished里直接delete,要调用deletelater;
reply=NULL; accessManager->deleteLater();
accessManager=NULL; downloadFinished();
} /***********更新进度条*************/
void ZRDownload::onDownloadProgress(qint64 bytesSent, qint64 bytesTotal){ double pre = double(bytesSent)/bytesTotal; progressPosition(pre);
} void ZRDownload::onReadyRead(){ file->write(reply->readAll());
}

上面的代码也是修改网上的代码,增加了QML调用的信息。

注意:项目文件pro中需要添加 QT += network

main.cpp:

添加 qmlRegisterType<ZRDownload>("xxx.xxx.ZRDownload", 1, 0, "ZRDownload");

QML调用:

 ZRDownload{
id:download
url:"http://xxx.xxx.com/xx.apk"
fileName:""
onProgressPosition:progressBar.update(pre) //自定义更新进度条函数
onDownloadFinished: {
//下载完成
}
} //启动下载
download.fileName=getAppPath();//设置保存目录,pc和安卓不同
download.httpDownload();

第三步,安装程序:

不同平台,安装程序的代码也不同,PC平台使用QProcess启动安装程序,安卓平台通过QAndroidJniObject调用Activity实现。下面是代码:

 #ifndef ZRINSTALL_H
#define ZRINSTALL_H #include <QObject>
#include <QString> class ZRInstall : public QObject
{
Q_OBJECT
Q_PROPERTY(QString fileName WRITE SetFileName)
public:
explicit ZRInstall(QObject *parent = ); void SetFileName(QString fn);
signals: public slots:
void install();
private:
QString m_FileName;
}; #endif // ZRINSTALL_H

头文件

 #include "zrinstall.h"
#include <QDebug>
#if defined(Q_OS_ANDROID)
#include <QtAndroid>
#else
#include <QProcess>
#endif ZRInstall::ZRInstall(QObject *parent) : QObject(parent)
{ } void ZRInstall::SetFileName(QString fn)
{
m_FileName = fn;
} void ZRInstall::install()
{
#if defined(Q_OS_ANDROID)
//安装apk
QAndroidJniObject path = QAndroidJniObject::fromString("file://"+m_FileName);
QAndroidJniObject uri = QAndroidJniObject::callStaticObjectMethod("android/net/Uri", "parse", "(Ljava/lang/String;)Landroid/net/Uri;", path.object<jstring>());
QAndroidJniObject param = QAndroidJniObject::getStaticObjectField<jstring>("android/content/Intent", "ACTION_VIEW");
QAndroidJniObject intent("android/content/Intent","(Ljava/lang/String;)V",param.object<jstring>());
QAndroidJniObject type = QAndroidJniObject::fromString("application/vnd.android.package-archive");
QAndroidJniObject result = intent.callObjectMethod("setDataAndTypeAndNormalize", "(Landroid/net/Uri;Ljava/lang/String;)Landroid/content/Intent;", uri.object<jobject>(), type.object<jstring>());
QtAndroid::startActivity(intent, , );
#else
//qDebug()<<m_FileName;
QProcess * proc = new QProcess();
proc->startDetached(m_FileName,QStringList());
delete proc;
#endif
}

CPP文件

 android{
QT += androidextras
}

项目文件pro

调用就不写了,可以参考上面download。

这样整个版本自动更新就写好了,有一些细节自己需要注意,如下载安装文件不同,安装目录不同。

QML 从无到有 3 (自动更新)的更多相关文章

  1. 解析大型.NET ERP系统 自动更新

    C/S架构的应用程序需要支持自动更新功能,当新版本程序发布后,正在运行的客户端能检测到新版本的程序,通知用户是否下载更新.工作以来参与过几个自动更新模块的设计与维护,撰文总结自动更新模块设计与实现. ...

  2. 扩展BindingList,防止增加、删除项时自动更新界面而不出现“跨线程操作界面控件 corss thread operation”异常

    在做界面程序时,常常需要一些数据类,界面元素通过绑定等方式显示出数据,然而由于UI线程不是线程安全的,一般都需要通过Invoke等方式来调用界面控件.但对于数据绑定bindingList而言,没法响应 ...

  3. 分析nuget源码,用nuget + nuget.server实现winform程序的自动更新

    源起 (个人理解)包管理最开始应该是从java平台下的maven开始吧,因为java的开发大多数是基于开源组件开发的,一个开源包在使用时很可能要去依赖其他的开源包,而且必须是特定的版本才可以.以往在找 ...

  4. ClickOnce部署(2):自动更新

    上次我们说了如何用最基本的方式用ClickOnce技术部署应用程序项目,本篇我们来认识一下如何让应用程序具备自动更新的功能. 我们依然通过实例来学习. 第一步,随便建一个应用程序项目,至于是控制台.W ...

  5. Android接入百度自动更新SDK

    一:前言 公司的app,上传到百度应用市场,然后说必须要接入百度的自动更新sdk才能上架,于是从百度官网上去下载jar包,下载的时候必须要带上数据统计,如果使用自动的jar包,还需要带上广告联盟,坑爹 ...

  6. C#之tcp自动更新程序

    .NETTCP自动更新程序有如下几步骤: 第一步:服务端开启监听 ServiceHost host; private void button1_Click(object sender, EventAr ...

  7. 使用 SVN Hook 实现服务器端代码自动更新

    之前的做法是客户端提交代码之后,再去服务器端项目中 svn up 一下来更新代码,让服务器端的项目更新到最新版本.可以编写一个 post-commit 钩子脚本来实现服务器端代码的自动更新,它在 SV ...

  8. git 远程版本库,github提供服务原理,git自动更新发送邮件

    1.安装好Linux,安装好Git(192.168.1.239) 2.创建一个用户zph(让此用户提供git on server),密码设置为12345678 # useradd zph # pass ...

  9. 【原创】我所理解的自动更新-APP发布与后台发布

    发布后台 创建渠道:添加新的渠道,设置渠道名称,自动生成渠道id.    查看渠道:查看渠道基本信息,渠道app版本号,资源版本号,是否开启更新.    创建/更新APP:选择打包ios,androi ...

随机推荐

  1. golang struct扩展函数参数命名警告

    今天在使用VSCode编写golang代码时,定义一个struct,扩展几个方法,如下: package storage import ( "fmt" "github.c ...

  2. Ubuntu搭建lnmp环境

    1.安装nginx 安装 sudo apt-get install nginx 服务启动.停止.重启 /etc/init.d/nginx start /usr/sbin/nginx -c /etc/n ...

  3. pandas基础-Python3

    未完 for examples: example 1: # Code based on Python 3.x # _*_ coding: utf-8 _*_ # __Author: "LEM ...

  4. 多线程条件通行工具——CountDownLatch

    CountDownLatch的作用是,线程进入等待后,需要计数器达到0才能通行. CountDownLatch(int)构造方法,指定初始计数. await()等待计数减至0. await(long, ...

  5. SharePonit 2010 更改另存为列表模板的语言类型

    从朋友处得来一个列表模板:AccessApplicationSharePoint.stp 将其通过:网站操作----网站设置----列表模板,上传进去.然后去创建列表,发现找不到此模板. 根据多年老司 ...

  6. NSURLSession详解

    导语 现在NSURLConnection在开发中会使用的越来越少,iOS9已经将NSURLConnection废弃,现在最低版本一般适配iOS7,所以也可以使用. NSURLConnection相对于 ...

  7. 2-1 Linux 操作系统及常用命令

    根据马哥linux初级视频 2-1.2-2来编辑 1. GUI与CLI GUI: Graphic User Interface CLI: Command Line Interface 注:在Windo ...

  8. TCP三次握手图解

  9. 【Java并发编程实战】-----“J.U.C”:CAS操作

    CAS,即Compare and Swap,中文翻译为"比较并交换". 对于JUC包中,CAS理论是实现整个java并发包的基石.从整体来看,concurrent包的实现示意图如下 ...

  10. Entity Framework 6 Recipes 2nd Edition(11-1)译 -> 从“模型定义”函数返回一个标量值

    第11章函数 函数提供了一个有力代码复用机制, 并且让你的代码保持简洁和易懂. 它们同样也是EF运行时能利用的数据库层代码.函数有几类: Rowset Functions, 聚合函数, Ranking ...