首先要看一下官方文档
官方热更新范例
官方热更新文档
官方热更新API
官方 version_generator.js 文件
首先我们要熟悉一下官方的热更新文档,了解热更新机制。其次自己要去通过实践来熟悉一下。
官方实例几处需要注意的,会导致热更新出问题
参考这篇博客
-
热更新目录的储存
/** * 这里需要注意的是,不要将相同的路径重复添加。所以这里加了判断 */ // 在下载资源完毕后,加入资源搜索路径 var searchPaths = jsb.fileUtils.getSearchPaths(); var newPaths = this._assetsMng.getLocalManifest().getSearchPaths(); for(let i = 0; i < newPaths.length; i++){ if(searchPaths.indexOf(newPaths[i]) == -1){ Array.prototype.unshift.apply(searchPaths, newPaths[i]); } } cc.sys.localStorage.setItem('HotUpdateSearchPaths', JSON.stringify(searchPaths)); jsb.fileUtils.setSearchPaths(searchPaths);
-
在main.js 中
main.js
开头 添加读取热更新路径(HotUpdateSearchPaths),并且这是searchPaths// 在 main.js 的开头添加如下代码 if (jsb) { var hotUpdateSearchPaths = localStorage.getItem('HotUpdateSearchPaths'); if (hotUpdateSearchPaths) { jsb.fileUtils.setSearchPaths(JSON.parse(hotUpdateSearchPaths)); } }
-
热更新MD5校验问题
在官方的校验函数中,当一个文件下载完成的时候,要对资源进行验证,验证成功返回true,该文件标识更新成功。
但是官方范例没有提到如何在js里计算文件md5。并且官方的version_generator.js 在计算的时候有一处问题。md5 = crypto.createHash('md5').update(fs.readFileSync(subpath,"binary")).digest('hex');
这里fs.readFileSycn(subpath,“binary”)返回的并非二进制类型,而是String。这会导致非文本文件md5计算错误。如果写入到manifest的文件md5是错误的,你下载文件后,计算md5作比较当然就很难匹配上了。除此之外,我们在jsb里只能使用:
jsb.fileUtils.getStringFromFile(filePath); jsb.fileUtils.getDataFromFile(filePath);
来获取文件内容,但是
getStringFromFile()
无法获取非文本内容。所以我们只能使用getStringFromFile()
来获取二进制数据,它在js层面的师徒类型是Uint8Array 和 nodejsreadFileSync()
一致。
现在我们来修改一下官方的version_generator.js
md5 = crypto.createHash('md5').update(fs.readFileSync(subpath,"binary")).digest('hex');
改为:md5 = crypto.createHash('md5').update(fs.readFileSync(subpath)).digest('hex');
修改后的version_generator.js接下来我们实现 byteArray md5的计算, jsb_md5.js
下面直接上代码/** * from jsb_runtime_md5.js * @param {} data */ module.exports = function(data){ // for test/debug function fflog(msg) { try { console.log(msg); } catch(e) { } } // convert number to (unsigned) 32 bit hex, zero filled string function to_zerofilled_hex(n) { var t1 = (n >>> 24).toString(16); var t2 = (n & 0x00FFFFFF).toString(16); return "00".substr(0, 2 - t1.length) + t1 + "000000".substr(0, 6 - t2.length) + t2; } // convert a 64 bit unsigned number to array of bytes. Little endian function int64_to_bytes(num) { var retval = []; for (var i = 0; i < 8; i++) { retval.push(num & 0xFF); num = num >>> 8; } return retval; } // 32 bit left-rotation function rol(num, places) { return ((num << places) & 0xFFFFFFFF) | (num >>> (32 - places)); } // The 4 MD5 functions function fF(b, c, d) { return (b & c) | (~b & d); } function fG(b, c, d) { return (d & b) | (~d & c); } function fH(b, c, d) { return b ^ c ^ d; } function fI(b, c, d) { return c ^ (b | ~d); } // pick 4 bytes at specified offset. Little-endian is assumed function bytes_to_int32(arr, off) { return (arr[off + 3] << 24) | (arr[off + 2] << 16) | (arr[off + 1] << 8) | (arr[off]); } // convert the 4 32-bit buffers to a 128 bit hex string. (Little-endian is assumed) function int128le_to_hex(a, b, c, d) { var ra = ""; var t = 0; var ta = 0; for (var i = 3; i >= 0; i--) { ta = arguments[i]; t = (ta & 0xFF); ta = ta >>> 8; t = t << 8; t = t | (ta & 0xFF); ta = ta >>> 8; t = t << 8; t = t | (ta & 0xFF); ta = ta >>> 8; t = t << 8; t = t | ta; ra = ra + to_zerofilled_hex(t); } return ra; } // check input data type and perform conversions if needed if (!data instanceof Uint8Array){ fflog("input data type mismatch only support Uint8Array"); return null; } var databytes = []; for(var i = 0; i < data.byteLength;i++){ databytes.push(data[i]); } // save original length var org_len = databytes.length; // first append the "1" + 7x "0" databytes.push(0x80); // determine required amount of padding var tail = databytes.length % 64; // no room for msg length? if (tail > 56) { // pad to next 512 bit block for (var i = 0; i < (64 - tail); i++) { databytes.push(0x0); } tail = databytes.length % 64; } for (i = 0; i < (56 - tail); i++) { databytes.push(0x0); } // message length in bits mod 512 should now be 448 // append 64 bit, little-endian original msg length (in *bits*!) databytes = databytes.concat(int64_to_bytes(org_len * 8)); // initialize 4x32 bit state var h0 = 0x67452301; var h1 = 0xEFCDAB89; var h2 = 0x98BADCFE; var h3 = 0x10325476; // temp buffers var a = 0, b = 0, c