mirror of
https://gitee.com/dgflash/oops-framework.git
synced 2026-05-21 02:05:40 +08:00
212 lines
7.8 KiB
TypeScript
212 lines
7.8 KiB
TypeScript
import { error, log, native, sys } from "cc";
|
||
import { oops } from "../../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
||
|
||
/** 热更参数 */
|
||
export class HotOptions {
|
||
/** 获取到版本号信息 */
|
||
onVersionInfo: Function | null = null;
|
||
/** 发现新版本,请更新 */
|
||
onNeedToUpdate: Function | null = null;
|
||
/** 和远程版本一致,无须更新 */
|
||
onNoNeedToUpdate: Function | null = null;
|
||
/** 更新失败 */
|
||
onUpdateFailed: Function | null = null;
|
||
/** 更新完成 */
|
||
onUpdateSucceed: Function | null = null;
|
||
/** 更新进度 */
|
||
onUpdateProgress: Function | null = null;
|
||
|
||
check() {
|
||
for (let key in this) {
|
||
if (key !== 'check') {
|
||
if (!this[key]) {
|
||
log(`参数HotOptions.${key}未设置!`);
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
return true
|
||
}
|
||
}
|
||
|
||
/** 热更管理 */
|
||
export class Hot {
|
||
private assetsMgr: native.AssetsManager = null!;
|
||
private options: HotOptions | null = null;
|
||
private state = Hot.State.None;
|
||
private storagePath: string = "";
|
||
private manifest: string = "";
|
||
|
||
static State = {
|
||
None: 0,
|
||
Check: 1,
|
||
Update: 2,
|
||
}
|
||
|
||
/** 热更初始化 */
|
||
init(opt: HotOptions) {
|
||
if (!sys.isNative) {
|
||
return;
|
||
}
|
||
if (!opt.check()) {
|
||
return;
|
||
}
|
||
this.options = opt;
|
||
|
||
if (this.assetsMgr) {
|
||
return;
|
||
}
|
||
|
||
oops.res.load('project', (err: Error | null, res: any) => {
|
||
if (err) {
|
||
error("【热更新界面】缺少热更新配置文件");
|
||
return;
|
||
}
|
||
|
||
this.showSearchPath();
|
||
|
||
this.manifest = res.nativeUrl;
|
||
this.storagePath = `${native.fileUtils.getWritablePath()}/oops_framework_remote`;
|
||
this.assetsMgr = new native.AssetsManager(this.manifest, this.storagePath, (versionA, versionB) => {
|
||
console.log("【热更新】客户端版本: " + versionA + ', 当前最新版本: ' + versionB);
|
||
this.options?.onVersionInfo && this.options.onVersionInfo({ local: versionA, server: versionB });
|
||
|
||
let vA = versionA.split('.');
|
||
let vB = versionB.split('.');
|
||
for (let i = 0; i < vA.length; ++i) {
|
||
let a = parseInt(vA[i]);
|
||
let b = parseInt(vB[i] || '0');
|
||
if (a !== b) {
|
||
return a - b;
|
||
}
|
||
}
|
||
|
||
if (vB.length > vA.length) {
|
||
return -1;
|
||
}
|
||
else {
|
||
return 0;
|
||
}
|
||
});
|
||
|
||
// 设置验证回调,如果验证通过,则返回true,否则返回false
|
||
this.assetsMgr.setVerifyCallback((path: string, asset: jsb.ManifestAsset) => {
|
||
// 压缩资源时,我们不需要检查其md5,因为zip文件已被删除
|
||
var compressed = asset.compressed;
|
||
// 检索正确的md5值
|
||
var expectedMD5 = asset.md5;
|
||
// 资源路径是相对路径,路径是绝对路径
|
||
var relativePath = asset.path;
|
||
// 资源文件的大小,但此值可能不存在
|
||
var size = asset.size;
|
||
|
||
return true;
|
||
});
|
||
|
||
var localManifest = this.assetsMgr.getLocalManifest();
|
||
console.log('【热更新】热更资源存放路径: ' + this.storagePath);
|
||
console.log('【热更新】本地资源配置路径: ' + this.manifest);
|
||
console.log('【热更新】本地包地址: ' + localManifest.getPackageUrl());
|
||
console.log('【热更新】远程 project.manifest 地址: ' + localManifest.getManifestFileUrl());
|
||
console.log('【热更新】远程 version.manifest 地址: ' + localManifest.getVersionFileUrl());
|
||
|
||
this.checkUpdate();
|
||
});
|
||
}
|
||
|
||
/** 删除热更所有存储文件 */
|
||
clearHotUpdateStorage() {
|
||
native.fileUtils.removeDirectory(this.storagePath);
|
||
}
|
||
|
||
// 检查更新
|
||
checkUpdate() {
|
||
if (!this.assetsMgr) {
|
||
console.log('【热更新】请先初始化')
|
||
return;
|
||
}
|
||
|
||
if (this.assetsMgr.getState() === jsb.AssetsManager.State.UNINITED) {
|
||
error('【热更新】未初始化')
|
||
return;
|
||
}
|
||
if (!this.assetsMgr.getLocalManifest().isLoaded()) {
|
||
console.log('【热更新】加载本地 manifest 失败 ...');
|
||
return;
|
||
}
|
||
this.assetsMgr.setEventCallback(this.onHotUpdateCallBack.bind(this));
|
||
this.state = Hot.State.Check;
|
||
// 下载version.manifest,进行版本比对
|
||
this.assetsMgr.checkUpdate();
|
||
}
|
||
|
||
/** 开始更热 */
|
||
hotUpdate() {
|
||
if (!this.assetsMgr) {
|
||
console.log('【热更新】请先初始化')
|
||
return
|
||
}
|
||
this.assetsMgr.setEventCallback(this.onHotUpdateCallBack.bind(this));
|
||
this.state = Hot.State.Update;
|
||
this.assetsMgr.update();
|
||
}
|
||
|
||
private onHotUpdateCallBack(event: native.EventAssetsManager) {
|
||
let code = event.getEventCode();
|
||
switch (code) {
|
||
case native.EventAssetsManager.ALREADY_UP_TO_DATE:
|
||
console.log("【热更新】当前版本与远程版本一致且无须更新");
|
||
this.options?.onNoNeedToUpdate && this.options.onNoNeedToUpdate(code)
|
||
break;
|
||
case native.EventAssetsManager.NEW_VERSION_FOUND:
|
||
console.log('【热更新】发现新版本,请更新');
|
||
this.options?.onNeedToUpdate && this.options.onNeedToUpdate(code, this.assetsMgr!.getTotalBytes());
|
||
break;
|
||
case native.EventAssetsManager.ASSET_UPDATED:
|
||
console.log('【热更新】资产更新');
|
||
break;
|
||
case native.EventAssetsManager.UPDATE_PROGRESSION:
|
||
if (this.state === Hot.State.Update) {
|
||
// event.getPercent();
|
||
// event.getPercentByFile();
|
||
// event.getDownloadedFiles() + ' / ' + event.getTotalFiles();
|
||
// event.getDownloadedBytes() + ' / ' + event.getTotalBytes();
|
||
console.log('【热更新】更新中...', event.getDownloadedFiles(), event.getTotalFiles(), event.getPercent());
|
||
this.options?.onUpdateProgress && this.options.onUpdateProgress(event);
|
||
}
|
||
break;
|
||
case native.EventAssetsManager.UPDATE_FINISHED:
|
||
this.onUpdateFinished();
|
||
break;
|
||
default:
|
||
this.onUpdateFailed(code);
|
||
break;
|
||
}
|
||
}
|
||
|
||
private onUpdateFailed(code: any) {
|
||
this.assetsMgr.setEventCallback(null!)
|
||
this.options?.onUpdateFailed && this.options.onUpdateFailed(code);
|
||
}
|
||
|
||
private onUpdateFinished() {
|
||
this.assetsMgr.setEventCallback(null!);
|
||
let searchPaths = native.fileUtils.getSearchPaths();
|
||
let newPaths = this.assetsMgr.getLocalManifest().getSearchPaths();
|
||
Array.prototype.unshift.apply(searchPaths, newPaths);
|
||
localStorage.setItem('HotUpdateSearchPaths', JSON.stringify(searchPaths));
|
||
native.fileUtils.setSearchPaths(searchPaths);
|
||
|
||
console.log('【热更新】更新成功');
|
||
this.options?.onUpdateSucceed && this.options.onUpdateSucceed();
|
||
}
|
||
|
||
private showSearchPath() {
|
||
console.log("========================搜索路径========================");
|
||
let searchPaths = native.fileUtils.getSearchPaths();
|
||
for (let i = 0; i < searchPaths.length; i++) {
|
||
console.log("[" + i + "]: " + searchPaths[i]);
|
||
}
|
||
console.log("======================================================");
|
||
}
|
||
} |