新的需求出来啦,需要自动更新功能,不怕程序升级了。
自动更新,QML不好写,需要c++来辅助,这里就涉及QML中调用c++功能(这里就不写了,百度一下,很多)。
思路:获取版本》下载程序》安装程序
第一步,获取版本信息,可以通过XMLHttpRequest获取最新版本。
第二步,下载程序,通过Qt c++的QtNetwork:
头文件:
1 #ifndef ZRDOWNLOAD_H2 #define ZRDOWNLOAD_H
3
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10
11 class ZRDownload : publicQObject12 {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 voidSetUrl(QString u);22 QString GetFileName();23 voidSetFileName(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 protectedslots:37 voidhttpDownload();38 void replyFinished(QNetworkReply*reply);39 voidonDownloadProgress(qint64 bytesSent,qint64 bytesTotal);40 voidonReadyRead();41 };42
43 #endif //ZRDOWNLOAD_H
View Code
CPP文件:
#include "zrdownload.h"#includeZRDownload::ZRDownload(QObject*parent) : QObject(parent)
{
accessManager=NULL;
reply=NULL;
}
ZRDownload::~ZRDownload()
{
}
QString ZRDownload::GetUrl()
{returnurl;
}voidZRDownload::SetUrl(QString u)
{
url=u;
}
QString ZRDownload::GetFileName()
{returnfileName;
}voidZRDownload::SetFileName(QString fn)
{
fileName=fn;
}voidZRDownload::httpDownload(){
file=newQFile(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();deletefile;
file=NULL;
}else{//处理错误
}
reply->deleteLater();//要删除reply,但是不能在repyfinished里直接delete,要调用deletelater;
reply=NULL;
accessManager->deleteLater();
accessManager=NULL;
downloadFinished();
}/***********更新进度条*************/
voidZRDownload::onDownloadProgress(qint64 bytesSent, qint64 bytesTotal){double pre = double(bytesSent)/bytesTotal;
progressPosition(pre);
}voidZRDownload::onReadyRead(){
file->write(reply->readAll());
}
View Code
上面的代码也是修改网上的代码,增加了QML调用的信息。
注意:项目文件pro中需要添加 QT+= network
main.cpp:
添加 qmlRegisterType("xxx.xxx.ZRDownload",1,0,"ZRDownload");
QML调用:
1 ZRDownload{2 id:download3 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_H2 #define ZRINSTALL_H
3
4 #include
5 #include
6
7 class ZRInstall : publicQObject8 {9 Q_OBJECT10 Q_PROPERTY(QString fileName WRITE SetFileName)11 public:12 explicit ZRInstall(QObject *parent = 0);13
14 voidSetFileName(QString fn);15 signals:16
17 publicslots:18 voidinstall();19 private:20 QString m_FileName;21 };22
23 #endif //ZRINSTALL_H
头文件
1 #include "zrinstall.h"
2 #include
3 #if defined(Q_OS_ANDROID)
4 #include
5 #else
6 #include
7 #endif
8
9 ZRInstall::ZRInstall(QObject *parent) : QObject(parent)10 {11
12 }13
14 voidZRInstall::SetFileName(QString fn)15 {16 m_FileName =fn;17 }18
19 voidZRInstall::install()20 {21 #if defined(Q_OS_ANDROID)
22 //安装apk
23 QAndroidJniObject path = QAndroidJniObject::fromString("file://"+m_FileName);24 QAndroidJniObject uri = QAndroidJniObject::callStaticObjectMethod("android/net/Uri", "parse", "(Ljava/lang/String;)Landroid/net/Uri;", path.object());25 QAndroidJniObject param = QAndroidJniObject::getStaticObjectField("android/content/Intent", "ACTION_VIEW");26 QAndroidJniObject intent("android/content/Intent","(Ljava/lang/String;)V",param.object());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(), type.object());29 QtAndroid::startActivity(intent, 1001, 0);30 #else
31 //qDebug()<
32 QProcess * proc = newQProcess();33 proc->startDetached(m_FileName,QStringList());34 deleteproc;35 #endif
36 }
CPP文件
1 android{2 QT +=androidextras3 }
项目文件pro
调用就不写了,可以参考上面download。
这样整个版本自动更新就写好了,有一些细节自己需要注意,如下载安装文件不同,安装目录不同。
原文:http://www.cnblogs.com/SamFang/p/5996056.html