首页 > 代码库 > QML 从无到有 3 (自动更新)

QML 从无到有 3 (自动更新)

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

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

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

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

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

头文件:

技术分享
 1 #ifndef ZRDOWNLOAD_H 2 #define ZRDOWNLOAD_H 3  4 #include <QObject> 5 #include <QtNetwork/QNetworkAccessManager> 6 #include <QFile> 7 #include <QtNetwork/QNetworkReply> 8 #include <QtNetwork/QNetworkRequest> 9 #include <QIODevice>10 11 class ZRDownload : public QObject12 {13     Q_OBJECT14     Q_PROPERTY(QString url READ GetUrl WRITE SetUrl)15     Q_PROPERTY(QString fileName READ GetFileName WRITE SetFileName)16 public:17     explicit ZRDownload(QObject *parent = 0);18     ~ZRDownload();19 20     QString GetUrl();21     void SetUrl(QString u);22     QString GetFileName();23     void SetFileName(QString fn);24 private:25     QString url;26     QString fileName;27     QFile *file;28     QNetworkAccessManager *accessManager;29     QNetworkRequest request;30     QNetworkReply *reply;31 32 signals:33     void progressPosition(double pre);  //更新进度条信号34     void downloadFinished();            //结束信号35 36 protected slots:37     void httpDownload();38     void replyFinished(QNetworkReply*reply);39     void onDownloadProgress(qint64 bytesSent,qint64 bytesTotal);40     void onReadyRead();41 };42 43 #endif // ZRDOWNLOAD_H
View Code

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());}
View Code

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

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

main.cpp:

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

QML调用:

 

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

 

第三步,安装程序:

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

技术分享
 1 #ifndef ZRINSTALL_H 2 #define ZRINSTALL_H 3  4 #include <QObject> 5 #include <QString> 6  7 class ZRInstall : public QObject 8 { 9     Q_OBJECT10     Q_PROPERTY(QString fileName WRITE SetFileName)11 public:12     explicit ZRInstall(QObject *parent = 0);13 14     void SetFileName(QString fn);15 signals:16 17 public slots:18     void install();19 private:20     QString m_FileName;21 };22 23 #endif // ZRINSTALL_H
头文件
技术分享
 1 #include "zrinstall.h" 2 #include <QDebug> 3 #if defined(Q_OS_ANDROID) 4 #include <QtAndroid> 5 #else 6 #include <QProcess> 7 #endif 8  9 ZRInstall::ZRInstall(QObject *parent) : QObject(parent)10 {11 12 }13 14 void ZRInstall::SetFileName(QString fn)15 {16     m_FileName = fn;17 }18 19 void ZRInstall::install()20 {21 #if defined(Q_OS_ANDROID)22     //安装apk23     QAndroidJniObject path = QAndroidJniObject::fromString("file://"+m_FileName);24     QAndroidJniObject uri = QAndroidJniObject::callStaticObjectMethod("android/net/Uri", "parse", "(Ljava/lang/String;)Landroid/net/Uri;", path.object<jstring>());25     QAndroidJniObject param = QAndroidJniObject::getStaticObjectField<jstring>("android/content/Intent", "ACTION_VIEW");26     QAndroidJniObject intent("android/content/Intent","(Ljava/lang/String;)V",param.object<jstring>());27     QAndroidJniObject type = QAndroidJniObject::fromString("application/vnd.android.package-archive");28     QAndroidJniObject result = intent.callObjectMethod("setDataAndTypeAndNormalize", "(Landroid/net/Uri;Ljava/lang/String;)Landroid/content/Intent;", uri.object<jobject>(), type.object<jstring>());29     QtAndroid::startActivity(intent, 1001, 0);30 #else31     //qDebug()<<m_FileName;32     QProcess * proc = new QProcess();33     proc->startDetached(m_FileName,QStringList());34     delete proc;35 #endif36 }
CPP文件
技术分享
1 android{2     QT += androidextras3 }
项目文件pro

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

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

 

 

QML 从无到有 3 (自动更新)