基于Tauri的跨平台游戏登录器实践 您所在的位置:网站首页 前端跨平台兼容 基于Tauri的跨平台游戏登录器实践

基于Tauri的跨平台游戏登录器实践

2023-12-25 16:04| 来源: 网络整理| 查看: 265

需求背景

近期接到需求,需要做一个游戏登录器,即类似于wegame的一个桌面应用,可以通过登录器来实现游戏的管理。对比了目前流行的跨平台桌面应用框架 electron 、nwjs 、tauri,决定尝试一下tauri,毕竟是真的轻量,还能借机学习一下rust,很完美。

Tauri简介

Tauri是基于rust开发的跨平台应用框架,使用系统自带的webview渲染ui。Tauri 在 Windows 上使用 Microsoft Edge WebView2,在 macOS 上使用 WKWebView,在 Linux 上使用 webkitgtk。目前新的alpha版本已经支持了移动端。

Tauri的优点:

轻量,打包快且体积小 高性能,内存占用少 安全

Tauri的缺点:

依赖系统的webview版本,可能存在兼容问题(目前还没遇到) 调试页面时,mac上是Safari的界面,个人不是很习惯.. 跨平台编译流程繁琐,目前只提供了github action,代码不在github上就很...只有win打win的包,mac打mac的包 学习成本微高,需要学习新语言rust,rust的学习曲线又是出了名的陡峭。(但是可以学学rust,毕竟在工程化领域很吃香) 中文资料较少,遇到问题要花更长的时间解决(如果有chatgpt辅助会好些)

!!!请不要盲目使用Tauri,要根据项目的实际情况选择,重要紧急的项目不推荐使用

窗口设置

tauri的配置文件是/src-tauri/tauri.conf.json,配置文件的详细说明参见官网tauri.app/zh-cn/v1/ap…。窗口相关的配置在tauri.window中,如宽、高、是否可拖动、是否全屏等。image.pngdecorations设置为false时,窗口不会展示最大化、最小化、关闭等工具栏按钮,如果需要这些功能,需要手动调用@tauri-apps/api/window中的setMinSize``setMaxSize方法。!!注意

decorations为false时 窗口会自动偏移,需要设置center为true 窗口会无法拖动,如果需要能够拖动,需要在外层的dom节点上添加data-tauri-drag-region属性 setMinSize``setMaxSize等所有js api在使用时,需要先在tauri.conf.json``tauri.allowlist中进行声明。 通信

前端调用rust

tauri提供了command系统,用于从 web 应用程序调用 Rust 函数。 command可以接受参数并返回结果, 也可以返回错误。如何使用command?

在rust的函数上添加#[tauri::command]注释,函数名即为command的名称 在main函数中使用invoke_handler注入command,多个command传递数组 在js代码中,从@tauri-apps/api/tauri中导入invoke函数,invoke('command_name')调用

!!注意

command传递参数时,如果变量使用了驼峰命名,在rust中接收到的变量会被转化为snake形势,如图,invokeMessage被转化为了invoke_message。image.png invoke方法是异步的,可以使用await方式调用 事件

可以通过触发和监听事件,从rust向js或者反过来传递消息。事件可以是全局事件,也可以指定窗口,没什么特殊用法,参见官网tauri.app/zh-cn/v1/gu…。

文件下载

游戏相关的资源都存放在oss上,下载或更新时需要使用http库拉取文件,这里使用了reqwest,crates.io/就像是npm一样,我们可以在上面搜索需要使用的第三方包,然后通过cargo安装。下载功能的实现参考了FishLauncher和douyin-downloader。文件下载主要有两个点需要考虑:

下载的进度条 断点续传 进度条

当前进度 = 当前已下载的大小 / 总文件大小构造一个client实例后,很容就能得到当前下载文件的总大小和当前已下载的大小,触发progress事件,然后在js中监听,获取事件参数,计算进度并展示,部分代码如下:

let client = reqwest::Client::new(); let response = client .get(&url) .headers(headers) .send() .await .or(Err(format!("Failed to GET from '{}'", &url)))?; // 文件总大小 let source_size = response .content_length() .ok_or(format!("Failed to get content length from '{}'", &url))?; // 已经下载的大小 let mut download_size: u64 = 0; // 下载流 let mut stream = response.bytes_stream(); while let Some(item) = stream.next().await { let chunk = item.or(Err(format!("Error while downloading file")))?; download_size += chunk.len() as u64; // 触发事件 window .emit( "progress", Payload { total: source_size, done: download_size, }, ) .unwrap(); file .write(&chunk) .or(Err(format!("Error while writing to file")))?; }

断点续传

游戏文件一般都超过500M,需要考虑中断下载后继续下载的情况,即断点续传。阿里云oss支持这个功能,所以使用起来很简单,在http请求中添加header字段range,服务器就知道该返回哪一块的数据回来。具体操作如下:

保存已经下载的文件大小 download_bytes 每次开始下载前,检查download_bytes的值是否大于0 大于0,进入断点续传逻辑 打开原来的文件,而不是创建新文件,要使用追加的模式 在header中添加range字段 否则正常下载 下载完成后,重置download_bytes的值

部分代码如下:

// 根据download_bytes判断创建文件还是打开原有文件 let mut file = if download_bytes > 0 { OpenOptions::new().append(true).open(&folder).or(Err(format!("Failed to open file '{}'", folder)))? } else { File::create(&folder).or(Err(format!("Failed to create file '{}'", folder)))? }; let mut headers = reqwest::header::HeaderMap::new(); headers.append(USER_AGENT, user_agent.parse().unwrap()); // 添加RANGE if download_bytes > 0 { headers.append(RANGE, format!("bytes={}-", bytes).parse().unwrap()); } // 要保证进度条的准确 let source_size = response .content_length() .ok_or(format!("Failed to get content length from '{}'", &url))? + download_bytes; let mut download_size: u64 = download_bytes;

!!注意:

多文件同时下载时,要注意进度条的变化,最好先获取多个文件的总大小,计算总的进度。否则会0-100%乱闪。 断点续传时,由于使用了range,reqwest获取到的文件总大小并不是实际的文件总大小。

自更新

打包

参见文档 tauri.app/zh-cn/v1/gu…如果我们需要校验更新是否安全,需要在tauri.conf.json中设置_Public-key,_ 打包时会生成对应包的签名,需要配置在更新文件中_。参见 tauri.app/zh-cn/v1/gu…。运行下方的命令,项目根目录下,会生成_Public-key和Private keytauri signer generate -w ~/.tauri/myapp.key需要注意的是,配置_Public-key_后,需要设置一个环境变量,TAURI_PRIVATE_KEY ,值为 _Private-key,_否则打包会失败。另外,在window上,最好在cmd命令行中运行打包命令。

更新json配置

tauri更新的服务配置也在tauri.conf.json配置文件中

"updater": { "active": true, "endpoints": [ "https://releases.myapp.com/{{target}}/{{current_version}}", "https://alioss/update.json" ], "dialog": true, "pubkey": "YOUR_UPDATER_SIGNATURE_PUBKEY_HERE", "windows": { "installMode": "passive" } }

endpoints就是tauri请求更新的地址,可以是接口,也可以是cdn上的json文件。如果是接口,需要按照tauri的要求返回对应的内容,参见文档 tauri.app/zh-cn/v1/gu…。我直接使用了cdn的方式,简单方便。dialog设置为true时,检测到新版本会使用系统内置的更新弹窗。如果想要保持多平台样式一致,需要设置为true,在代码中检测和监听更新,自定义操作和行为,参见文档 tauri.app/zh-cn/v1/gu… !!注意:windows.installMode这个值,代表更新后如何安装新包,默认是passive能看到进度条,quiet表示静默安装。如果设置为quiet,则程序需要**以管理员身份打开,**否则在更新时会死循环,一直安装一直重启。

其他 在windows上,使用winreg在运行时修改注册表 使用runas在运行时获取管理员权限 在界面上点击鼠标右键,会出现浏览器的右键菜单,需要视情况禁用或自定义 学习资料 rust语言圣经,非常棒的中文资料 狼叔的项目,rust for 前端 rust官方文档中文教程 tauri项目合集


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有