diff --git a/src/App.vue b/src/App.vue index 033e9ca..47d68bf 100644 --- a/src/App.vue +++ b/src/App.vue @@ -2,6 +2,7 @@ import { onLaunch, onShow, onHide } from "@dcloudio/uni-app"; import { getEvnUrl } from "@/request/base/config"; import { refreshToken } from "@/hooks/useGoLogin"; +import { updateManager } from "@/utils/UpdateManager"; let wasOffline = false; let isRecoveringNetwork = false; @@ -78,6 +79,8 @@ const checkNetworkStatus = () => { }; onLaunch(() => { + updateManager(); + uni.onNetworkStatusChange((res) => { if (!res.isConnected || res.networkType === "none") { wasOffline = true; diff --git a/src/uni_modules/uni-upgrade-center-app/changelog.md b/src/uni_modules/uni-upgrade-center-app/changelog.md new file mode 100644 index 0000000..f2ecf5c --- /dev/null +++ b/src/uni_modules/uni-upgrade-center-app/changelog.md @@ -0,0 +1,129 @@ +## 0.9.10(2026-04-27) +- 修复 uni-app-x 项目编译时 warning +## 0.9.9(2026-02-03) +- 修复 安卓端非强制更新 kotlin 报错 `onClick has not been intialized` +## 0.9.8(2026-01-05) +- 更新 移除 vapor 模式不支持的 class 选择器 +## 0.9.7(2025-07-28) +- 修复 使用腾讯云时,wgt 更新报错的Bug +- 改进 uni-app-x 平台弹窗该用 script setup 实现 +## 0.9.6(2025-04-01) +- 新增 升级中心适配鸿蒙 uni-app x **需要 HBuilderX 4.61+** +## 0.9.5(2025-02-06) +- 新增 完善下载失败时的处理逻辑 +## 0.9.4(2024-12-28) +- 修复 腾讯云在使用扩展存储时报错的 Bug +## 0.9.3(2024-12-23) +- 修复 升级中心在大屏上的显示效果 +## 0.9.2(2024-11-06) +- 更新 部分 ts 类型 +## 0.9.1(2024-11-01) +- 更新 支持 HarmonyOS Next 设备整包更新、wgt 更新。需要 `HBuilderX 4.32+` [详情](https://doc.dcloud.net.cn/uniCloud/upgrade-center.html#uni-upgrade-center-app-harmonyos) +## 0.9.0(2024-10-30) +- **重要更新** 在 uni-app x 项目中弃用之前弹窗方案使用[dialogPage](https://doc.dcloud.net.cn/uni-app-x/api/dialog-page.html)实现,需要 `HBuilderX 4.31+` +## 0.8.5(2024-10-26) +- 优化 去除不必要代码 +## 0.8.4(2024-10-26) +- 修复 uni-app x 项目升级到 4.31 alpha 后中间有空隙的Bug +## 0.8.3(2024-07-31) +- 修复 部分类型报错 +## 0.8.2(2024-07-15) +- 更新 static 下的静态图片放入 static/app 目录下,防止编译除 app 平台以外的平台时带入 +## 0.8.1(2024-04-28) +- 修复 在 HX 4.0.3+ uni-app x 项目运行到 Android 调不起安装的Bug +## 0.8.0(2024-04-15) +- 修复 更新弹窗 data 中新增初始化字段 +## 0.7.9(2024-03-15) +- 移除无用代码 +- 调整 is_silently 类型为可为 null +## 0.7.8(2024-01-04) +- 新增 移除无用代码 +## 0.7.7(2024-01-04) +- 新增 uni-app x 项目中新增 @show 回调 +## 0.7.6(2023-12-21) +- 修复 iOS使用升级中心云打包时报错(使用新版的 [uts-progressNotification](https://ext.dcloud.net.cn/plugin?name=uts-progressNotification) 插件,如果之前下载过请删除 `uts-progressNotification\utssdk\app-ios` 文件夹) +## 0.7.5(2023-12-12) +- 新增 通知栏进度条使用 uts-progressNotification 插件 +- 新增 依赖 uni-installApk、uts-progressNotification。使用前要安装插件三方依赖 +## 0.7.4(2023-11-29) +- 修复 uni-app-x 项目中由上版引发的无法升级的Bug +## 0.7.3(2023-11-27) +- 修复 在 uni-app x 中无更新时报错的Bug +## 0.7.2(2023-11-20) +- 新增 插件根目录 utils 文件夹中新增 check-update-nvue.js 文件(vue2 的 nvue 页面请引用该文件) +## 0.7.1(2023-11-17) +- 修复 运行至浏览器 ts 语法报错 +## 0.7.0(2023-11-10) +- 新增 兼容 uni-app x 项目 [详情](https://uniapp.dcloud.net.cn/uniCloud/upgrade-center.html) +## 0.6.5(2023-10-27) +- 修复 安装 wgt 报错 manifest.json 文件不存在的Bug +## 0.6.4(2023-09-01) +chore: 优化代码结构 +## 0.6.3(2023-08-30) +- 修复 下载 wgt 时如果后缀名不正确,重命名后安装 +## 0.6.2(2022-11-21) +- 处理 cloudfunctions 目录 +## 0.6.1(2022-08-17) +- 修复 后台添加应用市场,但都没有启用的情况下报错的Bug (需要 uni-admin 1.9.3+) +## 0.6.0(2022-07-19) +- 新增 支持多应用商店配置(需要 uni-admin 1.9.3+) +## 0.4.1(2022-05-27) +- 修复 上版引出的报错问题 +## 0.4.0(2022-05-27) +- 新增 Android 支持跳转手机自带商店,填写升级包地址时请填写跳转商店链接 +- 新增 改为云对象调用方式,使用更直观 +## 0.3.3(2022-04-14) +- 修复 调用 check-update,当 code 为 0 时没有回调 +## 0.3.2(2022-01-12) +- 优化显示逻辑 +## 0.3.1(2021-11-24) +- 修复 vue3 上图片不显示的Bug +## 0.3.0(2021-11-18) +- 移除 wgt 安装成功后提示,防止重启过快弹框不消失 +## 0.2.2(2021-08-25) +- 兼容vue3.0 +## 0.2.1(2021-07-26) +- 修复 使用腾讯云并手动填写地址时,导致下载链接失效的bug +## 0.2.0(2021-07-13) +- 更新文档 关于报错local_storage_key 为空,请不要将页面路径设置为pages.json中第一项 +## 0.1.9(2021-06-28) +- 更新文档 +- 修复 wgt安装失败时,按钮状态不对 +## 0.1.8(2021-06-16) +- 修复 跳转安装时,导致上次下载的apk还没安装就被删掉的bug +## 0.1.7(2021-06-03) +- 修改 移除static中的图片 +## 0.1.6(2021-06-03) +- 修改 下载更新按钮使用CSS渐变色 +## 0.1.5(2021-04-22) +- 更新check-update函数。现在返回一个Promise,有更新时成功回调,其他情况错误回调 +## 0.1.4(2021-04-13) +- 更新文档。明确云函数调用结果 +## 0.1.3(2021-04-13) +- 解耦云函数与弹框处理。utils中新增 call-check-version.js,可用于单独检测是否有更新 +## 0.1.2(2021-04-07) +- 更新版本对比函数 compare +## 0.1.1(2021-04-07) +- 修复 腾讯云空间下载链接不能下载问题 +## 0.1.0(2021-04-07) +- 新增使用uni.showModal提示升级示例 +- 修改iOS升级提示方式 +## 0.0.7(2021-04-02) +- 修复在iOS上打开弹框报错 +## 0.0.6(2021-04-01) +- 兼容旧版本安卓 +## 0.0.5(2021-04-01) +- 修复低版本安卓上进度条错位 +## 0.0.4(2021-04-01) +- 更新readme +- 修复check-update语法错误 +## 0.0.3(2021-04-01) +- 新增前台更新弹框,详见readme +- 更新前台检查更新方法 + +## 0.0.2(2021-03-29) +- 更新文档 +- 移除 dependencies + +## 0.0.1(2021-03-25) +- 升级中心前台检查更新 diff --git a/src/uni_modules/uni-upgrade-center-app/package.json b/src/uni_modules/uni-upgrade-center-app/package.json new file mode 100644 index 0000000..56f2d7e --- /dev/null +++ b/src/uni_modules/uni-upgrade-center-app/package.json @@ -0,0 +1,122 @@ +{ + "id": "uni-upgrade-center-app", + "displayName": "升级中心 uni-upgrade-center - App", + "version": "0.9.10", + "description": "uni升级中心 - 客户端检查更新", + "keywords": [ + "uniCloud", + "update", + "升级", + "wgt" +], + "repository": "https://gitee.com/dcloud/uni-upgrade-center/tree/master/uni_modules/uni-upgrade-center-app", + "engines": { + "HBuilderX": "^4.31", + "uni-app": "^4.35", + "uni-app-x": "^4.65" + }, + "dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "插件不采集任何数据", + "permissions": "无" + }, + "npmurl": "", + "type": "unicloud-template-page", + "darkmode": "x", + "i18n": "x", + "widescreen": "√" + }, + "uni_modules": { + "dependencies": [ + "uts-progressNotification", + "uts-openSchema" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "√", + "aliyun": "√", + "alipay": "√" + }, + "client": { + "uni-app": { + "vue": { + "vue2": "√", + "vue3": "√" + }, + "web": { + "safari": "-", + "chrome": "-" + }, + "app": { + "vue": "√", + "nvue": { + "extVersion": "0.8.3", + "minVersion": "" + }, + "android": { + "extVersion": "0.8.3", + "minVersion": "21" + }, + "ios": { + "extVersion": "0.8.3", + "minVersion": "12" + }, + "harmony": { + "extVersion": "0.9.1", + "minVersion": "12" + } + }, + "mp": { + "weixin": "x", + "alipay": "x", + "toutiao": "x", + "baidu": "x", + "kuaishou": "x", + "jd": "x", + "harmony": "x", + "qq": "x", + "lark": "x", + "xhs": "-" + }, + "quickapp": { + "huawei": "x", + "union": "x" + } + }, + "uni-app-x": { + "web": { + "safari": "x", + "chrome": "x" + }, + "app": { + "android": { + "extVersion": "0.9.0", + "minVersion": "21" + }, + "ios": { + "extVersion": "0.9.0", + "minVersion": "12" + }, + "harmony": "√" + }, + "mp": { + "weixin": "x" + } + } + } + } + } +} \ No newline at end of file diff --git a/src/uni_modules/uni-upgrade-center-app/pages/uni-app-x/upgrade-popup.uvue b/src/uni_modules/uni-upgrade-center-app/pages/uni-app-x/upgrade-popup.uvue new file mode 100644 index 0000000..6a30575 --- /dev/null +++ b/src/uni_modules/uni-upgrade-center-app/pages/uni-app-x/upgrade-popup.uvue @@ -0,0 +1,546 @@ + + + + + diff --git a/src/uni_modules/uni-upgrade-center-app/pages/upgrade-popup.vue b/src/uni_modules/uni-upgrade-center-app/pages/upgrade-popup.vue new file mode 100644 index 0000000..e9769d6 --- /dev/null +++ b/src/uni_modules/uni-upgrade-center-app/pages/upgrade-popup.vue @@ -0,0 +1,679 @@ + + + + + diff --git a/src/uni_modules/uni-upgrade-center-app/readme.md b/src/uni_modules/uni-upgrade-center-app/readme.md new file mode 100644 index 0000000..53ff781 --- /dev/null +++ b/src/uni_modules/uni-upgrade-center-app/readme.md @@ -0,0 +1 @@ +文档已移至 [uni-upgrade-center](https://uniapp.dcloud.net.cn/uniCloud/upgrade-center.html) \ No newline at end of file diff --git a/src/uni_modules/uni-upgrade-center-app/static/app/app_update_close.png b/src/uni_modules/uni-upgrade-center-app/static/app/app_update_close.png new file mode 100644 index 0000000..8b2ffe6 Binary files /dev/null and b/src/uni_modules/uni-upgrade-center-app/static/app/app_update_close.png differ diff --git a/src/uni_modules/uni-upgrade-center-app/static/app/bg_top.png b/src/uni_modules/uni-upgrade-center-app/static/app/bg_top.png new file mode 100644 index 0000000..015f698 Binary files /dev/null and b/src/uni_modules/uni-upgrade-center-app/static/app/bg_top.png differ diff --git a/src/uni_modules/uni-upgrade-center-app/uniCloud/database/db_init.json b/src/uni_modules/uni-upgrade-center-app/uniCloud/database/db_init.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/src/uni_modules/uni-upgrade-center-app/uniCloud/database/db_init.json @@ -0,0 +1 @@ +{} diff --git a/src/uni_modules/uni-upgrade-center-app/utils/call-check-version.ts b/src/uni_modules/uni-upgrade-center-app/utils/call-check-version.ts new file mode 100644 index 0000000..82b4de1 --- /dev/null +++ b/src/uni_modules/uni-upgrade-center-app/utils/call-check-version.ts @@ -0,0 +1,120 @@ +export type StoreListItem = { + enable : boolean + id : string + name : string + scheme : string + priority : number // 优先级 +} + +export type UniUpgradeCenterResult = { + _id : string + appid : string + name : string + title : string + contents : string + url : string // 安装包下载地址 + platform : Array // Array<'Android' | 'iOS' | 'Harmony'> + version : string // 版本号 1.0.0 + uni_platform : string // "android" | "ios" | 'harmony' + stable_publish : boolean // 是否是稳定版 + is_mandatory : boolean // 是否强制更新 + is_silently : boolean | null // 是否静默更新 + create_env : string // "upgrade-center" + create_date : number + message : string + code : number + + type : string // "native_app" | "wgt" + store_list : StoreListItem[] | null + min_uni_version : string | null // 升级 wgt 的最低 uni-app 版本 +} + +export default function () : Promise { + // #ifdef APP + return new Promise((resolve, reject) => { + const systemInfo = uni.getSystemInfoSync() + const appId = systemInfo.appId + const appVersion = systemInfo.appVersion //systemInfo.appVersion + // #ifndef UNI-APP-X + if (typeof appId === 'string' && typeof appVersion === 'string' && appId.length > 0 && appVersion.length > 0) { + plus.runtime.getProperty(appId, function (widgetInfo) { + if (widgetInfo.version) { + let data = { + action: 'checkVersion', + appid: appId, + appVersion: appVersion, + wgtVersion: widgetInfo.version + } + uniCloud.callFunction({ + name: 'uni-upgrade-center', + data, + success: (e) => { + resolve(e.result as UniUpgradeCenterResult) + }, + fail: (error) => { + reject(error) + } + }) + } else { + reject('widgetInfo.version is EMPTY') + } + }) + } else { + reject('plus.runtime.appid is EMPTY') + } + // #endif + // #ifdef UNI-APP-X + if (typeof appId === 'string' && typeof appVersion === 'string' && appId.length > 0 && appVersion.length > 0) { + let data = { + action: 'checkVersion', + appid: appId, + appVersion: appVersion, + is_uniapp_x: true, + wgtVersion: '0.0.0.0.0.1' + } + try { + uniCloud.callFunction({ + name: 'uni-upgrade-center', + data: data + }).then(res => { + const code = res.result['code'] + const codeIsNumber = ['Int', 'Long', 'number'].includes(typeof code) + if (codeIsNumber) { + if ((code as number) == 0) { + reject({ + code: res.result['code'], + message: res.result['message'] + }) + } else if ((code as number) < 0) { + reject({ + code: res.result['code'], + message: res.result['message'] + }) + } else { + const result = JSON.parse(JSON.stringify(res.result)) as UniUpgradeCenterResult + resolve(result) + } + } + }).catch((err : any | null) => { + const error = err as UniCloudError + if (error.errMsg == '未匹配到云函数[uni-upgrade-center]') + error.errMsg = '【uni-upgrade-center-app】未配置uni-upgrade-center,无法升级。参考: https://uniapp.dcloud.net.cn/uniCloud/upgrade-center.html' + reject(error.errMsg) + }) + } catch (e) { + reject(e.message) + } + } else { + reject('invalid appid or appVersion') + } + // #endif + }) + // #endif + // #ifndef APP + return new Promise((resolve, reject) => { + reject({ + message: '请在App中使用' + }) + }) + // #endif +} diff --git a/src/uni_modules/uni-upgrade-center-app/utils/check-update-nvue.js b/src/uni_modules/uni-upgrade-center-app/utils/check-update-nvue.js new file mode 100644 index 0000000..6c0d4bc --- /dev/null +++ b/src/uni_modules/uni-upgrade-center-app/utils/check-update-nvue.js @@ -0,0 +1,184 @@ +function callCheckVersion() { + // #ifdef APP-PLUS + return new Promise((resolve, reject) => { + plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) { + let data = { + action: 'checkVersion', + appid: plus.runtime.appid, + appVersion: plus.runtime.version, + wgtVersion: widgetInfo.version + } + uniCloud.callFunction({ + name: 'uni-upgrade-center', + data, + success: (e) => { + resolve(e) + }, + fail: (error) => { + reject(error) + } + }) + }) + }) + // #endif + // #ifndef APP-PLUS + return new Promise((resolve, reject) => {}) + // #endif +} + +// 推荐再App.vue中使用 +const PACKAGE_INFO_KEY = '__package_info__' + +export default function() { + // #ifdef APP-PLUS + return new Promise((resolve, reject) => { + callCheckVersion().then(async (e) => { + if (!e.result) return; + const { + code, + message, + is_silently, // 是否静默更新 + url, // 安装包下载地址 + platform, // 安装包平台 + type // 安装包类型 + } = e.result; + + // 此处逻辑仅为实例,可自行编写 + if (code > 0) { + // 腾讯云和阿里云下载链接不同,需要处理一下,阿里云会原样返回 + const { + fileList + } = await uniCloud.getTempFileURL({ + fileList: [url] + }); + if (fileList[0].tempFileURL) + e.result.url = fileList[0].tempFileURL; + + resolve(e) + + // 静默更新,只有wgt有 + if (is_silently) { + uni.downloadFile({ + url: e.result.url, + success: res => { + if (res.statusCode == 200) { + // 下载好直接安装,下次启动生效 + plus.runtime.install(res.tempFilePath, { + force: false + }); + } + } + }); + return; + } + + /** + * 提示升级一 + * 使用 uni.showModal + */ + // return updateUseModal(e.result) + + /** + * 提示升级二 + * 官方适配的升级弹窗,可自行替换资源适配UI风格 + */ + uni.setStorageSync(PACKAGE_INFO_KEY, e.result) + uni.navigateTo({ + url: `/uni_modules/uni-upgrade-center-app/pages/upgrade-popup?local_storage_key=${PACKAGE_INFO_KEY}`, + fail: (err) => { + console.error('更新弹框跳转失败', err) + uni.removeStorageSync(PACKAGE_INFO_KEY) + } + }) + + return + } else if (code < 0) { + // TODO 云函数报错处理 + console.error(message) + return reject(e) + } + return resolve(e) + }).catch(err => { + // TODO 云函数报错处理 + console.error(err.message) + reject(err) + }) + }); + // #endif +} + +/** + * 使用 uni.showModal 升级 + */ +function updateUseModal(packageInfo) { + const { + title, // 标题 + contents, // 升级内容 + is_mandatory, // 是否强制更新 + url, // 安装包下载地址 + platform, // 安装包平台 + type // 安装包类型 + } = packageInfo; + + let isWGT = type === 'wgt' + let isiOS = !isWGT ? platform.includes('iOS') : false; + let confirmText = isiOS ? '立即跳转更新' : '立即下载更新' + + return uni.showModal({ + title, + content: contents, + showCancel: !is_mandatory, + confirmText, + success: res => { + if (res.cancel) return; + + // 安装包下载 + if (isiOS) { + plus.runtime.openURL(url); + return; + } + + uni.showToast({ + title: '后台下载中……', + duration: 1000 + }); + + // wgt 和 安卓下载更新 + downloadTask = uni.downloadFile({ + url, + success: res => { + if (res.statusCode !== 200) { + console.error('下载安装包失败', err); + return; + } + // 下载好直接安装,下次启动生效 + plus.runtime.install(res.tempFilePath, { + force: false + }, () => { + if (is_mandatory) { + //更新完重启app + plus.runtime.restart(); + return; + } + uni.showModal({ + title: '安装成功是否重启?', + success: res => { + if (res.confirm) { + //更新完重启app + plus.runtime.restart(); + } + } + }); + }, err => { + uni.showModal({ + title: '更新失败', + content: err + .message, + showCancel: false + }); + }); + } + }); + } + }); +} diff --git a/src/uni_modules/uni-upgrade-center-app/utils/check-update.ts b/src/uni_modules/uni-upgrade-center-app/utils/check-update.ts new file mode 100644 index 0000000..8c27d17 --- /dev/null +++ b/src/uni_modules/uni-upgrade-center-app/utils/check-update.ts @@ -0,0 +1,228 @@ +import callCheckVersion, { UniUpgradeCenterResult } from "./call-check-version" +import { platform_iOS } from './utils' +// #ifdef UNI-APP-X +import { openSchema } from '@/uni_modules/uts-openSchema' +// #endif + +// 推荐再App.vue中使用 +const PACKAGE_INFO_KEY = '__package_info__' +// #ifdef APP-HARMONY +export default function (component?: any) : Promise { +// #endif +// #ifndef APP-HARMONY +export default function () : Promise { +// #endif + return new Promise((resolve, reject) => { + callCheckVersion().then(async (uniUpgradeCenterResult) => { + // NOTE uni-app x 3.96 解构有问题 + const code = uniUpgradeCenterResult.code + const message = uniUpgradeCenterResult.message + const url = uniUpgradeCenterResult.url // 安装包下载地址 + // 此处逻辑仅为示例,可自行编写 + if (code > 0) { + // 腾讯云获取下载链接 + if (/^cloud:\/\//.test(url)) { + const tcbRes = await uniCloud.getTempFileURL({ fileList: [url] }); + if (typeof tcbRes.fileList[0].tempFileURL !== 'undefined') uniUpgradeCenterResult.url = tcbRes.fileList[0].tempFileURL; + } + + /** + * 提示升级一 + * 使用 uni.showModal + */ + // return updateUseModal(uniUpgradeCenterResult) + + // #ifndef UNI-APP-X + // 静默更新,只有wgt有 + if (uniUpgradeCenterResult.is_silently) { + uni.downloadFile({ + url: uniUpgradeCenterResult.url, + success: res => { + if (res.statusCode == 200) { + // 下载好直接安装,下次启动生效 + plus.runtime.install(res.tempFilePath, { + force: false + }); + } + } + }); + return; + } + // #endif + + /** + * 提示升级二 + * 官方适配的升级弹窗,可自行替换资源适配UI风格 + */ + // #ifndef UNI-APP-X + // #ifdef APP-PLUS + uni.setStorageSync(PACKAGE_INFO_KEY, uniUpgradeCenterResult) + uni.navigateTo({ + url: `/uni_modules/uni-upgrade-center-app/pages/upgrade-popup?local_storage_key=${PACKAGE_INFO_KEY}`, + fail: (err) => { + console.error('更新弹框跳转失败', err) + uni.removeStorageSync(PACKAGE_INFO_KEY) + } + }) + // #endif + // #ifdef APP-HARMONY + if (component) { + component.show(true, uniUpgradeCenterResult) + } else { + reject({ + code: -1, + message: '在 HarmonyOS Next 平台请传递组件使用' + }) + } + // #endif + // #endif + // #ifdef UNI-APP-X + uni.setStorageSync(PACKAGE_INFO_KEY, uniUpgradeCenterResult) + uni.openDialogPage({ + url: `/uni_modules/uni-upgrade-center-app/pages/uni-app-x/upgrade-popup?local_storage_key=${PACKAGE_INFO_KEY}`, + disableEscBack: true, + fail: (err) => { + console.error('更新弹框跳转失败', err) + uni.removeStorageSync(PACKAGE_INFO_KEY) + } + }) + // #endif + + return resolve(uniUpgradeCenterResult) + } else if (code < 0) { + console.error(message) + return reject(uniUpgradeCenterResult) + } + return resolve(uniUpgradeCenterResult) + }).catch((err) => { + reject(err) + }) + }); + } + +/** + * 使用 uni.showModal 升级 + */ +function updateUseModal(packageInfo : UniUpgradeCenterResult) : void { + // #ifdef APP + const { + title, // 标题 + contents, // 升级内容 + is_mandatory, // 是否强制更新 + url, // 安装包下载地址 + type, + platform + } = packageInfo; + + let isWGT = type === 'wgt' + let isiOS = !isWGT ? platform.includes(platform_iOS) : false; + + // #ifndef UNI-APP-X + let confirmText = isiOS ? '立即跳转更新' : '立即下载更新' + // #endif + // #ifdef UNI-APP-X + let confirmText = '立即下载更新' + // #endif + + uni.showModal({ + title, + content: contents, + showCancel: !is_mandatory, + confirmText, + success: res => { + if (res.cancel) return; + + if (isiOS) { + // iOS 平台跳转 AppStore + // #ifndef UNI-APP-X + plus.runtime.openURL(url); + // #endif + // #ifdef UNI-APP-X + openSchema(url) + // #endif + return; + } + + uni.showToast({ + title: '后台下载中……', + duration: 1000 + }); + + // wgt 和 安卓下载更新 + uni.downloadFile({ + url, + success: res => { + if (res.statusCode !== 200) { + console.error('下载安装包失败'); + return; + } + // 下载好直接安装,下次启动生效 + // uni-app x 项目没有 plus5+ 故使用条件编译 + // #ifndef UNI-APP-X + plus.runtime.install(res.tempFilePath, { + force: false + }, () => { + if (is_mandatory) { + //更新完重启app + // #ifdef APP-PLUS + plus.runtime.restart(); + // #endif + // #ifdef APP-HARMONY + uni.showModal({ + title: '安装成功', + content: '请手动重启应用', + showCancel: false, + success: res => { + plus.runtime.quit(); + } + }); + // #endif + return; + } + uni.showModal({ + title: '安装成功是否重启?', + success: res => { + if (res.confirm) { + //更新完重启app + // #ifdef APP-PLUS + plus.runtime.restart(); + // #endif + // #ifdef APP-HARMONY + plus.runtime.quit(); + // #endif + } + } + }); + }, err => { + uni.showModal({ + title: '更新失败', + content: err + .message, + showCancel: false + }); + }); + // #endif + + // #ifdef UNI-APP-X + uni.installApk({ + filePath: res.tempFilePath, + success: () => { + uni.showModal({ + title: '安装成功请手动重启' + }); + }, + fail: err => { + uni.showModal({ + title: '更新失败', + content: err.errMsg, + showCancel: false + }); + } + }); + // #endif + } + }); + } + }); + // #endif +} diff --git a/src/uni_modules/uni-upgrade-center-app/utils/utils.ts b/src/uni_modules/uni-upgrade-center-app/utils/utils.ts new file mode 100644 index 0000000..414e096 --- /dev/null +++ b/src/uni_modules/uni-upgrade-center-app/utils/utils.ts @@ -0,0 +1,46 @@ +export const platform_iOS: string = 'iOS'; +export const platform_Android: string = 'Android'; +export const platform_Harmony: string = 'Harmony'; + +/** + * 对比版本号,如需要,请自行修改判断规则 + * 支持比对 ("3.0.0.0.0.1.0.1", "3.0.0.0.0.1") ("3.0.0.1", "3.0") ("3.1.1", "3.1.1.1") 之类的 + * @param {Object} v1 + * @param {Object} v2 + * v1 > v2 return 1 + * v1 < v2 return -1 + * v1 == v2 return 0 + */ +export function compare(v_1: string = '0', v_2: string = '0') { + const v1: string[] = String(v_1).split('.'); + const v2: string[] = String(v_2).split('.'); + const minVersionLens = Math.min(v1.length, v2.length); + + let result = 0; + for (let i = 0; i < minVersionLens; i++) { + const curV1 = Number(v1[i]); + const curV2 = Number(v2[i]); + + if (curV1 > curV2) { + result = 1; + break; + } else if (curV1 < curV2) { + result = -1; + break; + } + } + + if (result === 0 && v1.length !== v2.length) { + const v1BiggerThenv2 = v1.length > v2.length; + const maxLensVersion = v1BiggerThenv2 ? v1 : v2; + for (let i = minVersionLens; i < maxLensVersion.length; i++) { + const curVersion = Number(maxLensVersion[i]); + if (curVersion > 0) { + v1BiggerThenv2 ? (result = 1) : (result = -1); + break; + } + } + } + + return result; +} \ No newline at end of file diff --git a/src/uni_modules/uts-openSchema/changelog.md b/src/uni_modules/uts-openSchema/changelog.md new file mode 100644 index 0000000..ac488d0 --- /dev/null +++ b/src/uni_modules/uts-openSchema/changelog.md @@ -0,0 +1,13 @@ +## 1.1.3(2025-09-12) +- 鸿蒙平台 新增 打开 url 错误时输出 +- iOS平台 修复 语法报黄问题 +## 1.1.2(2025-03-20) +- 更新 支持鸿蒙 +## 1.1.1(2024-12-16) +- 修复 canOpenURL 在安卓端可能会报类型错误的问题 +## 1.1.0(2024-12-06) +- 新增 canOpenURL UTS API,可用此API判断url是否可以跳转 +## 1.0.1(2024-11-13) +- 修复 Android 打开部分 schema 时没有跳转到目标应用的 Bug +## 1.0.0(2024-04-25) +- 更新 在 Android 和 iOS 上打开链接的 UTS API diff --git a/src/uni_modules/uts-openSchema/package.json b/src/uni_modules/uts-openSchema/package.json new file mode 100644 index 0000000..2225c04 --- /dev/null +++ b/src/uni_modules/uts-openSchema/package.json @@ -0,0 +1,124 @@ +{ + "id": "uts-openSchema", + "displayName": "uts-openSchema", + "version": "1.1.3", + "description": "在 Android、iOS、HarmonyOS 上打开链接的 UTS API", + "keywords": [ + "uts-openSchema" +], + "repository": "", + "engines": { + "HBuilderX": "^4.0", + "uni-app": "^4.75", + "uni-app-x": "^4.75" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "", + "darkmode": "x", + "i18n": "x", + "widescreen": "x" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "√", + "aliyun": "√", + "alipay": "√" + }, + "client": { + "uni-app": { + "vue": { + "vue2": { + "extVersion": "1.0.0", + "minVersion": "" + }, + "vue3": { + "extVersion": "1.0.0", + "minVersion": "" + } + }, + "web": { + "safari": "x", + "chrome": "x" + }, + "app": { + "vue": { + "extVersion": "1.0.0", + "minVersion": "" + }, + "nvue": "-", + "android": { + "extVersion": "1.0.0", + "minVersion": "21" + }, + "ios": { + "extVersion": "1.0.0", + "minVersion": "12" + }, + "harmony": { + "extVersion": "1.1.2", + "minVersion": "5.0.0" + } + }, + "mp": { + "weixin": "x", + "alipay": "x", + "toutiao": "x", + "baidu": "x", + "kuaishou": "x", + "jd": "x", + "harmony": "x", + "qq": "x", + "lark": "x" + }, + "quickapp": { + "huawei": "x", + "union": "x" + } + }, + "uni-app-x": { + "web": { + "safari": "x", + "chrome": "x" + }, + "app": { + "android": { + "extVersion": "1.0.0", + "minVersion": "21" + }, + "ios": { + "extVersion": "1.0.0", + "minVersion": "12" + }, + "harmony": { + "extVersion": "1.1.2", + "minVersion": "5.0.0" + } + }, + "mp": { + "weixin": "x" + } + } + } + } + } +} \ No newline at end of file diff --git a/src/uni_modules/uts-openSchema/readme.md b/src/uni_modules/uts-openSchema/readme.md new file mode 100644 index 0000000..2b48c22 --- /dev/null +++ b/src/uni_modules/uts-openSchema/readme.md @@ -0,0 +1,59 @@ +# uts-openSchema + +打开链接,支持: + +1. 打开外部 App +2. 使用浏览器打开链接 +3. 打开地图到指定地点 +4. ... + +## 使用 + +1. 安装此插件 +2. 在要使用的地方 `import` 导入 + ```ts + import { openSchema, canOpenURL } from '@/uni_modules/uts-openSchema' + ``` +3. 直接调用 `openSchema` 方法: + ```ts + // #ifdef UNI-APP-X + // 使用外部浏览器打开指定URL + openSchema('https://uniapp.dcloud.io/uni-app-x') + + // #ifdef APP-ANDROID + // Android 使用应用商店打开指定App + openSchema('market://details?id=com.tencent.mm') + + // Android 打开地图坐标 + // 可以先用canOpenURL判断是否安装了地图软件 + if (canOpenURL('androidamap://')) { + openSchema('androidamap://viewMap?sourceApplication=Hello%20uni-app&poiname=DCloud&lat=39.9631018208&lon=116.3406135236&dev=0') + } else { + console.log('未安装高德地图') + } + // #endif --> + + // #ifdef APP-IOS + // 打开 AppStore 到搜索页 + openSchema('itms-apps://search.itunes.apple.com//WebObjects//MZSearch.woa/wa/search?media=software<erm=') + + // 打开 iOS 地图坐标 + openSchema('http://maps.apple.com/?q=Mexican+Restaurant&sll=50.894967,4.341626&z=10&t=s') + // #endif --> + + // #endif --> + ``` + +### 参数 + +- openSchema(url: string) // `url`:要打开的链接 `必填` `不为空字符串` + +## 相关开发文档 + +[UTS 语法](https://uniapp.dcloud.net.cn/tutorial/syntax-uts.html) + +[UTS API插件](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html) + +[UTS 组件插件](https://uniapp.dcloud.net.cn/plugin/uts-component.html) + +[Hello UTS](https://gitcode.net/dcloud/hello-uts) diff --git a/src/uni_modules/uts-openSchema/utssdk/app-android/config.json b/src/uni_modules/uts-openSchema/utssdk/app-android/config.json new file mode 100644 index 0000000..bf95925 --- /dev/null +++ b/src/uni_modules/uts-openSchema/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "21" +} \ No newline at end of file diff --git a/src/uni_modules/uts-openSchema/utssdk/app-android/index.uts b/src/uni_modules/uts-openSchema/utssdk/app-android/index.uts new file mode 100644 index 0000000..9f9316f --- /dev/null +++ b/src/uni_modules/uts-openSchema/utssdk/app-android/index.uts @@ -0,0 +1,27 @@ +import Intent from 'android.content.Intent' +import Uri from 'android.net.Uri' +import { OpenSchema, CanOpenURL } from '../interface.uts' + +export const openSchema : OpenSchema = function (url : string) { + if (canOpenURL(url)) { + const context = UTSAndroid.getUniActivity()! + const uri = Uri.parse(url) + const intent = new Intent(Intent.ACTION_VIEW, uri) + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + intent.setData(uri) + context.startActivity(intent) + } else { + console.error('[uts-openSchema] url param Error:', JSON.stringify(url)) + } +} + +export const canOpenURL : CanOpenURL = function (url : string) : boolean { + if (typeof url === 'string' && url.length > 0) { + const context = UTSAndroid.getUniActivity()! + const uri = Uri.parse(url) + const intent = new Intent(Intent.ACTION_VIEW, uri) + return intent.resolveActivity(context.packageManager) != null ? true : false + } else { + return false + } +} diff --git a/src/uni_modules/uts-openSchema/utssdk/app-harmony/index.uts b/src/uni_modules/uts-openSchema/utssdk/app-harmony/index.uts new file mode 100644 index 0000000..b1fd020 --- /dev/null +++ b/src/uni_modules/uts-openSchema/utssdk/app-harmony/index.uts @@ -0,0 +1,21 @@ +import { bundleManager, common } from '@kit.AbilityKit'; +import OpenLinkOptions from '@ohos.app.ability.OpenLinkOptions' +import { getAbilityContext } from '@dcloudio/uni-runtime' +import { OpenSchema, CanOpenURL } from '../interface.uts' + + +export const openSchema : OpenSchema = function (url : string) : void { + (getAbilityContext() as common.UIAbilityContext)?.openLink(url, { + appLinkingOnly: false + } as OpenLinkOptions) +} + + +export const canOpenURL : CanOpenURL = function (url : string) : boolean { + try { + return bundleManager.canOpenLink(url) + } catch (error) { + console.error('[uts-openSchema] url param Error:', JSON.stringify(url)) + return false + } +} diff --git a/src/uni_modules/uts-openSchema/utssdk/app-ios/config.json b/src/uni_modules/uts-openSchema/utssdk/app-ios/config.json new file mode 100644 index 0000000..f272043 --- /dev/null +++ b/src/uni_modules/uts-openSchema/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "12.0" +} \ No newline at end of file diff --git a/src/uni_modules/uts-openSchema/utssdk/app-ios/index.uts b/src/uni_modules/uts-openSchema/utssdk/app-ios/index.uts new file mode 100644 index 0000000..623df34 --- /dev/null +++ b/src/uni_modules/uts-openSchema/utssdk/app-ios/index.uts @@ -0,0 +1,22 @@ +import { UIApplication } from 'UIKit' +import { URL } from 'Foundation' +import { OpenSchema, CanOpenURL } from '../interface.uts' + +export const openSchema : OpenSchema = function (url : string) : void { + if (canOpenURL(url)) { + let uri = new URL(string = url) + UIApplication.shared.open(uri!) + } else { + console.error('[uts-openSchema] url param Error: ', url) + } +} + +export const canOpenURL : CanOpenURL = function (url : string) : boolean { + if (typeof url == 'string' && url.length > 0) { + let uri = new URL(string = url) + if (uri != null && UIApplication.shared.canOpenURL(uri!)) { + return true + } + } + return false +} diff --git a/src/uni_modules/uts-openSchema/utssdk/interface.uts b/src/uni_modules/uts-openSchema/utssdk/interface.uts new file mode 100644 index 0000000..1140d3c --- /dev/null +++ b/src/uni_modules/uts-openSchema/utssdk/interface.uts @@ -0,0 +1,2 @@ +export type OpenSchema = (url : string) => void +export type CanOpenURL = (url : string) => boolean diff --git a/src/uni_modules/uts-openSchema/utssdk/web/index.uts b/src/uni_modules/uts-openSchema/utssdk/web/index.uts new file mode 100644 index 0000000..6e5419c --- /dev/null +++ b/src/uni_modules/uts-openSchema/utssdk/web/index.uts @@ -0,0 +1,12 @@ +import { OpenSchema, CanOpenURL } from '../interface.uts' + +export const openSchema : OpenSchema = function (url : string) : void { + location.href = url; +} + +export const canOpenURL : CanOpenURL = function (url : string) : boolean { + if (url != "") { + return true; + } + return false; +} diff --git a/src/uni_modules/uts-progressNotification/changelog.md b/src/uni_modules/uts-progressNotification/changelog.md new file mode 100644 index 0000000..b7caf4e --- /dev/null +++ b/src/uni_modules/uts-progressNotification/changelog.md @@ -0,0 +1,28 @@ +## 1.1.2(2025-02-10) +修复某些情况通过点击通知消息无法拉起App的bug +## 1.1.1(2024-09-03) +去除TypeScript警告 +## 1.1.0(2024-03-08) +修复uniapp打包报错问题 +## 1.0.9(2024-02-29) +去除代码过时警告 +## 1.0.8(2023-12-21) +去除app-ios目录 +## 1.0.7(2023-12-11) +去除无用代码 +## 1.0.6(2023-12-11) +修改文档 +## 1.0.5(2023-12-11) +1.修改插件名称 +2.修改插件引入方式为import导入 +## 1.0.4(2023-11-30) +1. createNotificationProgress增加`onClick`回调 +2.修复在小米部分系统上,通知消息会归类于不重要通知的bug +## 1.0.3(2023-11-28) +更新截图 +## 1.0.2(2023-11-28) +修改资源的包名 +## 1.0.1(2023-11-28) +更新文档 +## 1.0.0(2023-11-28) +Android通知栏显示进度插件 diff --git a/src/uni_modules/uts-progressNotification/package.json b/src/uni_modules/uts-progressNotification/package.json new file mode 100644 index 0000000..9f2adb1 --- /dev/null +++ b/src/uni_modules/uts-progressNotification/package.json @@ -0,0 +1,85 @@ +{ + "id": "uts-progressNotification", + "displayName": "uts-progressNotification", + "version": "1.1.2", + "description": "uts-progressNotification", + "keywords": [ + "progressNotification" +], + "repository": "", + "engines": { + "HBuilderX": "^3.91" + }, + "dcloudext": { + "type": "uts", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "插件不采集任何数据", + "permissions": "TargetSDKVersion33以上时需配置\n`android.permission.POST_NOTIFICATIONS`" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y", + "alipay": "n" + }, + "client": { + "Vue": { + "vue2": "y", + "vue3": "y" + }, + "App": { + "app-android": { + "minVersion": "19" + }, + "app-ios": "n", + "app-harmony": "u" + }, + "H5-mobile": { + "Safari": "n", + "Android Browser": "n", + "微信浏览器(Android)": "n", + "QQ浏览器(Android)": "n" + }, + "H5-pc": { + "Chrome": "n", + "IE": "n", + "Edge": "n", + "Firefox": "n", + "Safari": "n" + }, + "小程序": { + "微信": "n", + "阿里": "n", + "百度": "n", + "字节跳动": "n", + "QQ": "n", + "钉钉": "n", + "快手": "n", + "飞书": "n", + "京东": "n" + }, + "快应用": { + "华为": "n", + "联盟": "n" + } + } + } + } +} diff --git a/src/uni_modules/uts-progressNotification/readme.md b/src/uni_modules/uts-progressNotification/readme.md new file mode 100644 index 0000000..87d8576 --- /dev/null +++ b/src/uni_modules/uts-progressNotification/readme.md @@ -0,0 +1,71 @@ +# uts-progressNotification + +## 使用说明 + +Android平台创建显示进度的通知栏消息 + +**注意: 需要自定义基座,否则点击通知栏消息不会拉起应用** + +### 导入 + +需要import导入插件 + +### createNotificationProgress(options : CreateNotificationProgressOptions) : void, + +创建显示进度的通知栏消息 + +参数说明 + +``` +export type CreateNotificationProgressOptions = { + /** + * 通知标题 + * @defaultValue 应用名称 + */ + title ?: string | null + /** + * 通知内容 + */ + content : string, + /** + * 进度 + */ + progress : number, + /** + * 点击通知消息回调 + * @defaultValue null + */ + onClick? : (() => void) | null +} +``` + +### finishNotificationProgress(options: FinishNotificationProgressOptions) : void + +完成时调用的API,比如下载完成后需要显示下载完成并隐藏进度时调用。 + +参数说明 + + +``` +export type FinishNotificationProgressOptions = { + /** + * 通知标题 + * @defaultValue 应用名称 + */ + title ?: string | null + /** + * 通知内容 + */ + content : string, + /** + * 点击通知消息回调 + */ + onClick : () => void +} +``` + + +### cancelNotificationProgress() : void + +取消通知消息显示 + diff --git a/src/uni_modules/uts-progressNotification/utssdk/app-android/AndroidManifest.xml b/src/uni_modules/uts-progressNotification/utssdk/app-android/AndroidManifest.xml new file mode 100644 index 0000000..93749e9 --- /dev/null +++ b/src/uni_modules/uts-progressNotification/utssdk/app-android/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/src/uni_modules/uts-progressNotification/utssdk/app-android/TransparentActivity.uts b/src/uni_modules/uts-progressNotification/utssdk/app-android/TransparentActivity.uts new file mode 100644 index 0000000..be33350 --- /dev/null +++ b/src/uni_modules/uts-progressNotification/utssdk/app-android/TransparentActivity.uts @@ -0,0 +1,62 @@ +import Activity from "android.app.Activity"; +import Bundle from 'android.os.Bundle'; +import Build from 'android.os.Build'; +import View from 'android.view.View'; +import Color from 'android.graphics.Color'; +import WindowManager from 'android.view.WindowManager'; +import { getGlobalNotificationProgressCallBack, getGlobalNotificationProgressFinishCallBack, setGlobalNotificationProgressCallBack, setGlobalNotificationProgressFinishCallBack} from './callbacks.uts'; +import { ACTION_DOWNLOAD_FINISH, ACTION_DOWNLOAD_PROGRESS } from "./constant.uts" + + +export class TransparentActivity extends Activity { + constructor() { + super() + } + + @Suppress("DEPRECATION") + override onCreate(savedInstanceState : Bundle | null) { + super.onCreate(savedInstanceState) + this.fullScreen(this) + const action = this.getIntent().getAction() + if (action == ACTION_DOWNLOAD_FINISH) { + setTimeout(() => { + getGlobalNotificationProgressFinishCallBack()?.() + setGlobalNotificationProgressFinishCallBack(() => { }) + }, 100) + this.overridePendingTransition(0, 0) + } + + if (action == ACTION_DOWNLOAD_PROGRESS) { + setTimeout(() => { + getGlobalNotificationProgressCallBack()?.() + setGlobalNotificationProgressCallBack(() => { }) + }, 100) + this.overridePendingTransition(0, 0) + } + + setTimeout(() => { + this.finish() + }, 20) + } + + + @Suppress("DEPRECATION") + private fullScreen(activity : Activity) { + if (Build.VERSION.SDK_INT >= 19) { + if (Build.VERSION.SDK_INT >= 21) { + const window = activity.getWindow(); + const decorView = window.getDecorView(); + const option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; + decorView.setSystemUiVisibility(option); + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + window.setStatusBarColor(Color.TRANSPARENT); + } else { + const window = activity.getWindow(); + const attributes = window.getAttributes(); + const flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; + attributes.flags |= flagTranslucentStatus; + window.setAttributes(attributes); + } + } + } +} diff --git a/src/uni_modules/uts-progressNotification/utssdk/app-android/callbacks.uts b/src/uni_modules/uts-progressNotification/utssdk/app-android/callbacks.uts new file mode 100644 index 0000000..68991d2 --- /dev/null +++ b/src/uni_modules/uts-progressNotification/utssdk/app-android/callbacks.uts @@ -0,0 +1,19 @@ +let globalNotificationProgressCallBack : (() => void) | null = () => { } +let globalNotificationProgressFinishCallBack : (() => void) | null = () => { } + +export function setGlobalNotificationProgressCallBack(callBack : (() => void) | null) : void { + globalNotificationProgressCallBack = callBack +} + +export function getGlobalNotificationProgressCallBack() : (() => void) | null { + return globalNotificationProgressCallBack +} + + +export function setGlobalNotificationProgressFinishCallBack(callBack : (() => void) | null) : void { + globalNotificationProgressFinishCallBack = callBack +} + +export function getGlobalNotificationProgressFinishCallBack() : (() => void) | null { + return globalNotificationProgressFinishCallBack +} diff --git a/src/uni_modules/uts-progressNotification/utssdk/app-android/config.json b/src/uni_modules/uts-progressNotification/utssdk/app-android/config.json new file mode 100644 index 0000000..7deedfa --- /dev/null +++ b/src/uni_modules/uts-progressNotification/utssdk/app-android/config.json @@ -0,0 +1,3 @@ +{ + "minSdkVersion": "19" +} \ No newline at end of file diff --git a/src/uni_modules/uts-progressNotification/utssdk/app-android/constant.uts b/src/uni_modules/uts-progressNotification/utssdk/app-android/constant.uts new file mode 100644 index 0000000..8652ac4 --- /dev/null +++ b/src/uni_modules/uts-progressNotification/utssdk/app-android/constant.uts @@ -0,0 +1,2 @@ +export const ACTION_DOWNLOAD_FINISH = "ACTION_DOWNLOAD_FINISH" +export const ACTION_DOWNLOAD_PROGRESS = "ACTION_DOWNLOAD_PROGRESS" \ No newline at end of file diff --git a/src/uni_modules/uts-progressNotification/utssdk/app-android/index.uts b/src/uni_modules/uts-progressNotification/utssdk/app-android/index.uts new file mode 100644 index 0000000..ac66a3a --- /dev/null +++ b/src/uni_modules/uts-progressNotification/utssdk/app-android/index.uts @@ -0,0 +1,156 @@ +import Build from 'android.os.Build'; +import Context from 'android.content.Context'; +import NotificationManager from 'android.app.NotificationManager'; +import NotificationChannel from 'android.app.NotificationChannel'; +import Notification from 'android.app.Notification'; +import Intent from 'android.content.Intent'; +import ComponentName from 'android.content.ComponentName'; +import PendingIntent from 'android.app.PendingIntent'; +import { CreateNotificationProgressOptions, FinishNotificationProgressOptions } from '../interface.uts'; +import { ACTION_DOWNLOAD_FINISH, ACTION_DOWNLOAD_PROGRESS } from "./constant.uts" + +import { setGlobalNotificationProgressCallBack, setGlobalNotificationProgressFinishCallBack } from './callbacks.uts'; + +export { TransparentActivity } from './TransparentActivity.uts'; + + +const DOWNLOAD_PROGRESS_NOTIFICATION_ID : Int = 7890 +const DC_DOWNLOAD_CHANNEL_ID = "下载文件" +const DC_DOWNLOAD_CHANNEL_NAME = "用于显示现在进度的渠道" + + +let notificationBuilder : Notification.Builder | null = null + +let timeId = -1 + +let histroyProgress = 0 + +let isProgress = false + + + +export function createNotificationProgress(options : CreateNotificationProgressOptions) : void { + const { content, progress, onClick } = options + + if (progress == 100) { + clearTimeout(timeId) + const context = UTSAndroid.getAppContext() as Context + realCreateNotificationProgress(options.title ?? getAppName(context), content, progress, onClick) + reset() + return + } + + histroyProgress = progress + if (timeId != -1) { + return + } + + const context = UTSAndroid.getAppContext() as Context + if (!isProgress) { + realCreateNotificationProgress(options.title ?? getAppName(context), content, histroyProgress, onClick) + isProgress = true + } else { + timeId = setTimeout(() => { + realCreateNotificationProgress(options.title ?? getAppName(context), content, histroyProgress, onClick) + timeId = -1 + }, 1000) + } +} + + +export function cancelNotificationProgress() : void { + const context = UTSAndroid.getAppContext() as Context + const notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + notificationManager.cancel(DOWNLOAD_PROGRESS_NOTIFICATION_ID) + reset() +} + + +function realCreateNotificationProgress(title : string, content : string, progress : number, cb : (() => void) | null) : void { + setGlobalNotificationProgressCallBack(cb) + const context = UTSAndroid.getAppContext() as Context + const notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + createDownloadChannel(notificationManager) + const builder = createNotificationBuilder(context) + builder.setProgress(100, progress.toInt(), false) + builder.setContentTitle(title) + builder.setContentText(content) + builder.setContentIntent(createPendingIntent(context, ACTION_DOWNLOAD_PROGRESS)); + notificationManager.notify(DOWNLOAD_PROGRESS_NOTIFICATION_ID, builder.build()) +} + + +export function finishNotificationProgress(options : FinishNotificationProgressOptions) { + setGlobalNotificationProgressFinishCallBack(options.onClick) + const context = UTSAndroid.getAppContext() as Context + const notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + createDownloadChannel(notificationManager) + const builder = createNotificationBuilder(context) + builder.setProgress(0, 0, false) + builder.setContentTitle(options.title ?? getAppName(context)) + builder.setContentText(options.content) + //小米rom setOngoing未false的时候,会被通知管理器归为不重要通知 + // builder.setOngoing(false) + builder.setAutoCancel(true); + builder.setContentIntent(createPendingIntent(context, ACTION_DOWNLOAD_FINISH)); + notificationManager.notify(DOWNLOAD_PROGRESS_NOTIFICATION_ID, builder.build()) + reset() +} + +function reset() { + isProgress = false + notificationBuilder = null + histroyProgress = 0 + if (timeId != -1) { + clearTimeout(timeId) + timeId = -1 + } +} + +function createPendingIntent(context : Context, action : string) : PendingIntent { + const intent = new Intent(action); + intent.setComponent(new ComponentName(context.getPackageName(), "uts.sdk.modules.utsProgressNotification.TransparentActivity")); + let flags = PendingIntent.FLAG_UPDATE_CURRENT; + if (Build.VERSION.SDK_INT >= 23) { + flags = PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE; + } + return PendingIntent.getActivity(context, DOWNLOAD_PROGRESS_NOTIFICATION_ID, intent, flags); +} + +function createDownloadChannel(notificationManager : NotificationManager) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + const channel = new NotificationChannel( + DC_DOWNLOAD_CHANNEL_ID, + DC_DOWNLOAD_CHANNEL_NAME, + NotificationManager.IMPORTANCE_LOW + ) + notificationManager.createNotificationChannel(channel) + } +} +@Suppress("DEPRECATION") +function createNotificationBuilder(context : Context) : Notification.Builder { + if (notificationBuilder == null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + notificationBuilder = new Notification.Builder(context, DC_DOWNLOAD_CHANNEL_ID) + } else { + notificationBuilder = new Notification.Builder(context) + } + notificationBuilder!.setSmallIcon(context.getApplicationInfo().icon) + notificationBuilder!.setOngoing(true) + notificationBuilder!.setSound(null) + } + return notificationBuilder! +} + +@Suppress("DEPRECATION") +function getAppName(context : Context) : string { + let appName = "" + try { + const packageManager = context.getPackageManager() + const applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0) + appName = packageManager.getApplicationLabel(applicationInfo) as string + } catch (e : Exception) { + e.printStackTrace() + } + return appName +} diff --git a/src/uni_modules/uts-progressNotification/utssdk/app-android/res/values/notification_progress_styles.xml b/src/uni_modules/uts-progressNotification/utssdk/app-android/res/values/notification_progress_styles.xml new file mode 100644 index 0000000..cc01105 --- /dev/null +++ b/src/uni_modules/uts-progressNotification/utssdk/app-android/res/values/notification_progress_styles.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/src/uni_modules/uts-progressNotification/utssdk/interface.uts b/src/uni_modules/uts-progressNotification/utssdk/interface.uts new file mode 100644 index 0000000..9570353 --- /dev/null +++ b/src/uni_modules/uts-progressNotification/utssdk/interface.uts @@ -0,0 +1,46 @@ +export type CreateNotificationProgressOptions = { + /** + * 通知标题 + * @defaultValue 应用名称 + */ + title ?: string | null + /** + * 通知内容 + */ + content : string, + /** + * 进度 + */ + progress : number, + /** + * 点击通知消息回调 + * @defaultValue null + */ + onClick? : (() => void) | null +} + + +export type FinishNotificationProgressOptions = { + /** + * 通知标题 + * @defaultValue 应用名称 + */ + title ?: string | null + /** + * 通知内容 + */ + content : string, + /** + * 点击通知消息回调 + */ + onClick : () => void +} + + +export type CreateNotificationProgress = (options : CreateNotificationProgressOptions) => void; + + +export type CancelNotificationProgress = () => void; + + +export type FinishNotificationProgress = (options: FinishNotificationProgressOptions) => void diff --git a/src/uni_modules/uts-progressNotification/utssdk/unierror.uts b/src/uni_modules/uts-progressNotification/utssdk/unierror.uts new file mode 100644 index 0000000..e69de29 diff --git a/src/utils/UpdateManager.js b/src/utils/UpdateManager.js index 29b7619..23e1736 100644 --- a/src/utils/UpdateManager.js +++ b/src/utils/UpdateManager.js @@ -1,27 +1,83 @@ -export const updateManager = () => { +// #ifdef APP-PLUS +import checkUpdate from "@/uni_modules/uni-upgrade-center-app/utils/check-update"; +// #endif + +let isCheckingAppUpdate = false; +let hasRegisteredMiniProgramUpdate = false; +const APP_UPDATE_CHECK_TIMEOUT = 30000; + +const formatUpdateError = (error) => { + if (!error) return ""; + if (typeof error === "string") return error; + return error.message || error.errMsg || JSON.stringify(error); +}; + +export const checkMiniProgramUpdate = () => { // #ifdef MP-WEIXIN || MP-TOUTIAO - const updateManager = uni.getUpdateManager(); + if (hasRegisteredMiniProgramUpdate) return; + hasRegisteredMiniProgramUpdate = true; + + const miniProgramUpdateManager = uni.getUpdateManager(); // 当向小程序后台请求完新版本信息,会进行回调 - updateManager.onCheckForUpdate((res) => { + miniProgramUpdateManager.onCheckForUpdate((res) => { console.log("onCheckForUpdate res:", res.hasUpdate); }); // 当新版本下载完成,会进行回调 - updateManager.onUpdateReady(() => { + miniProgramUpdateManager.onUpdateReady(() => { uni.showModal({ title: "更新提示", content: "新版本已经准备好,是否重启应用?", success: (res) => { if (res.confirm) { // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启 - updateManager.applyUpdate(); + miniProgramUpdateManager.applyUpdate(); } }, }); }); // 当新版本下载失败,会进行回调 - updateManager.onUpdateFailed(() => {}); + miniProgramUpdateManager.onUpdateFailed(() => {}); // #endif }; + +export const checkAppUpdate = () => { + // #ifdef APP-PLUS + if (isCheckingAppUpdate) return Promise.resolve(null); + + isCheckingAppUpdate = true; + + return new Promise((resolve) => { + let finished = false; + const finish = (result = null) => { + if (finished) return; + finished = true; + clearTimeout(timeoutTimer); + isCheckingAppUpdate = false; + resolve(result); + }; + + const timeoutTimer = setTimeout(() => { + finish(); + }, APP_UPDATE_CHECK_TIMEOUT); + + checkUpdate() + .then(finish) + .catch((error) => { + console.warn("App更新检查失败:", formatUpdateError(error)); + finish(); + }); + }); + // #endif + + // #ifndef APP-PLUS + return Promise.resolve(null); + // #endif +}; + +export const updateManager = () => { + checkMiniProgramUpdate(); + return checkAppUpdate(); +};