赞
踩
使用CMake编译的QT项目,版本:Sparkle 2
Sparkle是一个非常简单且易用的macOS应用程序更新框架,目前众多知名macOS App都在使用。
Sparkle的原理是根据提前配置好的xml文件地址,每次启动后解析xml,看看有没有比当前版本新的数据,有的话提示更新。 xml文件可以存在任何可以访问xml元数据的服务器,包括 GitHub 仓库。
github地址:https://github.com/sparkle-project/Sparkle
git clone --recursive https://github.com/sparkle-project/Sparkle
使用Xcode打开项目文件
1.可以选择支持两种架构的版本编译
2.点击运行按钮进行编译
该脚本目的生成公钥和私钥
根据提示信息将公钥添加到Info.plist
该脚本目的自动生成appcast.xml
./generate_appcast myapp_updates
myapp_updates是一个文件夹
- myapp_updates/
- ├── MyApp_1.2.0.zip
- ├── MyApp_1.2.0.html
- ├── appcast.xml
generate_appcast
工具生成或更新的文件,包含了所有可用更新的元数据。在运行工具之前,这个文件可能不存在,或者需要更新。检查最终生成的appcast.xml
- # 添加 Sparkle.framework
- set(SPARKLE_FRAMEWORK_DIR ${CMAKE_SOURCE_DIR}/你的目录/Sparkle.framework)
- set(SPARKLE_INCLUDE_DIR ${SPARKLE_FRAMEWORK_DIR}/Headers)
- include_directories(${SPARKLE_INCLUDE_DIR})
-
- add_executable(MyProject
- AutoUpgrade.h
- AutoUpgrade.cpp
- #与C++的桥接文件
- MacosAutoUpgrade.mm
- MacosAutoUpgrade.h
- )
-
- add_compile_options(-x objective-c++)
- target_link_libraries(Project PRIVATE ${SPARKLE_FRAMEWORK_DIR})
- #ifdef __APPLE__
- #include "MacosAutoUpgrade.h"
- #import <Sparkle/Sparkle.h>
- #include <QPushButton>
-
- @interface AppUpdaterDelegate : NSObject <SPUUpdaterDelegate>
-
- @property(nonatomic) SPUStandardUpdaterController *updaterController;
- @property(nonatomic) QObject *updaterObject;
-
- @end
-
- @implementation AppUpdaterDelegate
-
- - (instancetype)initWithUpdaterObject:(QObject *)updaterObject {
- self = [super init];
- if (self) {
- _updaterObject = updaterObject;
- }
- return self;
- }
-
- // 检查key至
- - (void)observeValueForKeyPath:(NSString *)keyPath
- ofObject:(id)object
- change:(NSDictionary<NSKeyValueChangeKey, id> *)change
- context:(void *)context {
- if ([keyPath isEqualToString:NSStringFromSelector(@selector(canCheckForUpdates))]) {
- bool canCheckForUpdates = [[change objectForKey:NSKeyValueChangeNewKey] boolValue];
- QMetaObject::invokeMethod(_updaterObject, "updateButtonState", Q_ARG(bool, canCheckForUpdates));
- } else {
- [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
- }
- }
-
- - (void)dealloc {
- @autoreleasepool {
- [_updaterController.updater removeObserver:self
- forKeyPath:NSStringFromSelector(@selector(canCheckForUpdates))];
- }
- }
-
- @end
-
- Updater::Updater(QPushButton *checkForUpdatesButton) {
- @autoreleasepool {
- _updaterDelegate = [[AppUpdaterDelegate alloc] initWithUpdaterObject:this];
- _updaterDelegate.updaterController =
- [[SPUStandardUpdaterController alloc] initWithStartingUpdater:YES
- updaterDelegate:_updaterDelegate
- userDriverDelegate:nil];
-
- connect(checkForUpdatesButton, &QPushButton::clicked, this, &Updater::checkForUpdates);
-
- [_updaterDelegate.updaterController.updater
- addObserver:_updaterDelegate
- forKeyPath:NSStringFromSelector(@selector(canCheckForUpdates))
- options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew)
- context:nil];
- }
-
- startAutomaticChecks();
- }
-
- // 主动检查更新,只要有最新版本无论是否点击忽略版本都展示升级界面
- void Updater::checkForUpdates() {
- @autoreleasepool {
- [_updaterDelegate.updaterController checkForUpdates:nil];
- }
- }
-
- // 自动检测更新时,如果待升级的版本已点击忽略,则不展示升级界面
- void Updater::startAutomaticChecks() {
- @autoreleasepool {
- // 开启自动检查更新
- _updaterDelegate.updaterController.updater.automaticallyChecksForUpdates = YES;
- // 每天检查一次
- _updaterDelegate.updaterController.updater.updateCheckInterval = 86400;
- // 已忽略的版本不展示升级界面
- [_updaterDelegate.updaterController.updater checkForUpdatesInBackground];
- }
- }
-
- void Updater::updateButtonState(bool canCheckForUpdates) {
- Q_EMIT buttonStateUpdated(canCheckForUpdates);
- }
-
- #endif
- #ifndef MACOS_AUTO_UPGRADE_H
- #define MACOS_AUTO_UPGRADE_H
-
- #include <QObject>
-
- class QPushButton;
-
- #ifdef __OBJC__
- @class AppUpdaterDelegate;
- #endif
-
- class Updater : public QObject {
- Q_OBJECT
- public:
- #ifdef __APPLE__
- Updater(QPushButton *checkForUpdatesButton);
- void startAutomaticChecks();
-
- signals:
- void buttonStateUpdated(bool canCheckForUpdates);
-
- private slots:
- void checkForUpdates();
- void updateButtonState(bool canCheckForUpdates);
-
- private:
- #ifdef __OBJC__
- AppUpdaterDelegate *_updaterDelegate;
- #else
- void *_updaterDelegate;
- #endif
- #endif
- };
-
- #endif // MACOS_AUTO_UPGRADE_H
- std::unique_ptr<Updater> auto_upgrade_ = nullptr;
- auto_upgrade_ = std::make_unique<Updater>(ui->pushButton);
- auto_upgrade_->startAutomaticChecks();
- QObject::connect(auto_upgrade_.get(), &Updater::buttonStateUpdated,
- ui->pushButton, &QPushButton::setEnabled);
- <!-- 用于比较版本 -->
- <key>CFBundleVersion</key>
- <string>1.0.2</string>
-
- <!-- 应用程序的最低系统要求 -->
- <key>LSMinimumSystemVersion</key>
- <string>12.5</string>
-
- <!-- 这个键用于启用或禁用自动更新检查。如果设置为 true,Sparkle 将自动检查更新 -->
- <key>SUEnableAutomaticChecks</key>
- <true/>
-
- <!-- 增加自动更新,无需交互选项 -->
- <key>SUAllowsAutomaticUpdates</key>
- <true/>
- <!-- 自动更新检查间隔时间(秒) -->
- <key>SUScheduledCheckInterval</key>
- <integer>86400</integer>
-
- <!-- 这是Sparkle用来检查更新的URL。指向一个XML文件,该文件包含应用程序的最新版本信息 -->
- <key>SUFeedURL</key>
- <string>https://yourwebsite.com/updates/appcast.xml</string>
-
- <!-- generate_keys生成的公钥 -->
- <key>SUPublicEDKey</key>
- <string>your public key</string>
如果升级失败,可以使用控制台查看具体报错信息。
1.查看用户日志
2.点击开始(抓取日志)
3.运行更新程序(等待更新失败)
4.点击暂停,停止抓取新日志
5.搜索你的项目名,查看对应升级模块日志查看错误
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。