HotUpdate.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. export class HotOptions {
  2. OnVersionInfo: Function;
  3. OnNeedToUpdate: Function;
  4. OnNoNeedToUpdate: Function;
  5. OnUpdateFailed: Function;
  6. OnUpdateSucceed: Function;
  7. OnUpdateProgress: Function;
  8. check() {
  9. for (let key in this) {
  10. if (key !== 'check') {
  11. if (!this[key]) {
  12. console.log(`参数HotOptions.${key}未设置!`);
  13. return false;
  14. }
  15. }
  16. }
  17. return true
  18. }
  19. }
  20. class Hot {
  21. _assetsMgr: jsb.AssetsManager = null;
  22. _options: HotOptions = null;
  23. _state = Hot.State.None;
  24. static State = {
  25. None: 0,
  26. Check: 1,
  27. Update: 2,
  28. }
  29. // 检查更新
  30. checkUpdate() {
  31. if (!this._assetsMgr) {
  32. console.log('请先初始化')
  33. return;
  34. }
  35. if (this._assetsMgr.getState() === jsb.AssetsManager.State.UNINITED) {
  36. cc.error('未初始化')
  37. return;
  38. }
  39. if (!this._assetsMgr.getLocalManifest().isLoaded()) {
  40. console.log('加载本地 manifest 失败 ...');
  41. return;
  42. }
  43. this._assetsMgr.setEventCallback(this._hotUpdateCallBack.bind(this));
  44. this._state = Hot.State.Check;
  45. // 下载version.manifest,进行版本比对
  46. this._assetsMgr.checkUpdate();
  47. }
  48. hotUpdate() {
  49. if (!this._assetsMgr) {
  50. console.log('请先初始化')
  51. return
  52. }
  53. this._assetsMgr.setEventCallback(this._hotUpdateCallBack.bind(this));
  54. this._state = Hot.State.Update;
  55. this._assetsMgr.update();
  56. }
  57. _hotUpdateCallBack(event: jsb.EventAssetsManager) {
  58. let code = event.getEventCode();
  59. console.log(`hotUpdate Code: ${code}`);
  60. switch (code) {
  61. case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
  62. case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
  63. case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
  64. console.log("无远程资源");
  65. this._options.OnNoNeedToUpdate && this._options.OnNoNeedToUpdate(code)
  66. break;
  67. case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
  68. console.log("已经和远程版本一致,无须更新");
  69. this._options.OnNoNeedToUpdate && this._options.OnNoNeedToUpdate(code)
  70. break;
  71. case jsb.EventAssetsManager.NEW_VERSION_FOUND:
  72. console.log('发现新版本,请更新');
  73. this._options.OnNeedToUpdate && this._options.OnNeedToUpdate(code);
  74. break;
  75. case jsb.EventAssetsManager.UPDATE_PROGRESSION:
  76. console.log('更新中...')
  77. if (this._state === Hot.State.Update) {
  78. this._options.OnUpdateProgress && this._options.OnUpdateProgress(event);
  79. } else {
  80. // 检查状态下,不回调更新进度
  81. }
  82. break;
  83. case jsb.EventAssetsManager.UPDATE_FINISHED:
  84. console.log('更新成功');
  85. this._onUpdateFinished();
  86. break;
  87. case jsb.EventAssetsManager.ASSET_UPDATED:
  88. // 不予理会的消息事件
  89. break;
  90. default:
  91. this._onUpdateFailed(code);
  92. break;
  93. }
  94. }
  95. _onUpdateFailed(code) {
  96. this._assetsMgr.setEventCallback(null)
  97. this._options.OnUpdateFailed && this._options.OnUpdateFailed(code);
  98. }
  99. // 更新完成
  100. _onUpdateFinished() {
  101. this._assetsMgr.setEventCallback(null)
  102. let searchPaths = jsb.fileUtils.getSearchPaths();
  103. let newPaths = this._assetsMgr.getLocalManifest().getSearchPaths();
  104. console.log("[HotUpdate] 搜索路径: " + JSON.stringify(newPaths));
  105. Array.prototype.unshift(searchPaths, newPaths);
  106. cc.sys.localStorage.setItem('HotUpdateSearchPaths', JSON.stringify(searchPaths));
  107. jsb.fileUtils.setSearchPaths(searchPaths);
  108. this._options.OnUpdateSucceed && this._options.OnUpdateSucceed();
  109. }
  110. showSearchPath() {
  111. console.log("========================搜索路径========================");
  112. let searchPaths = jsb.fileUtils.getSearchPaths();
  113. for (let i = 0; i < searchPaths.length; i++) {
  114. console.log("[" + i + "]: " + searchPaths[i]);
  115. }
  116. console.log("======================================================");
  117. }
  118. // ------------------------------初始化------------------------------
  119. init(manifest: cc.Asset, opt: HotOptions) {
  120. // console.log('aaaaaaaaa ')
  121. if (!cc.sys.isNative) {
  122. // console.log('111 ');
  123. return;
  124. }
  125. if (!opt.check()) {
  126. // console.log('222 ');
  127. return;
  128. }
  129. this._options = opt;
  130. if (this._assetsMgr) {
  131. // console.log('333 ');
  132. return;
  133. }
  134. // console.log('444 ');
  135. this.showSearchPath();
  136. let url = manifest.nativeUrl;
  137. if (cc.loader.md5Pipe) {
  138. url = cc.loader.md5Pipe.transformURL(url)
  139. }
  140. let storagePath = ((jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/') + 'remote-asset');
  141. // console.log('555 ');
  142. this._assetsMgr = new jsb.AssetsManager(url, storagePath, (versionA, versionB) => {
  143. // 比较版本
  144. console.log("客户端版本: " + versionA + ', 当前最新版本: ' + versionB);
  145. // this._options.OnVersionInfo({ local: versionA, server: versionB });
  146. let vA = versionA.split('.');
  147. let vB = versionB.split('.');
  148. for (let i = 0; i < vA.length; ++i) {
  149. let a = parseInt(vA[i]);
  150. let b = parseInt(vB[i] || '0');
  151. if (a !== b) {
  152. return a - b;
  153. }
  154. }
  155. if (vB.length > vA.length) {
  156. return -1;
  157. } else {
  158. return 0;
  159. }
  160. });
  161. this._assetsMgr.setVerifyCallback((assetsFullPath, asset) => {
  162. let { compressed, md5, path, size } = asset;
  163. if (compressed) {
  164. return true;
  165. } else {
  166. return true;
  167. }
  168. })
  169. if (cc.sys.os === cc.sys.OS_ANDROID) {
  170. // 安卓手机设置 最大并发任务数量限制为2
  171. // this._assetsMgr.setMaxConcurrentTask(10);
  172. }
  173. let localManifest = this._assetsMgr.getLocalManifest()
  174. console.log('[HotUpdate] 热更新资源存放路径: ' + storagePath);
  175. console.log('[HotUpdate] 本地manifest路径: ' + url);
  176. console.log('[HotUpdate] local packageUrl: ' + localManifest.getPackageUrl());
  177. console.log('[HotUpdate] project.manifest remote url: ' + localManifest.getManifestFileUrl());
  178. console.log('[HotUpdate] version.manifest remote url: ' + localManifest.getVersionFileUrl());
  179. }
  180. }
  181. let hotInstance = new Hot();
  182. export default hotInstance;