cocos 通过 electron 打包成 exe 文件,实现通信问题
首先,我使用的 cocos 版本是 2.4.12,遇到一个问题,是啥子呢,就是我要把用 cocos 开发出来的项目打包成一个 exe 可执行程序,使用的是 electron ,现在我有一个需求,就是在 cocos 中开发一个“退出”按钮,点击这个按钮的时候,关闭 exe 程序。
cocos关闭exe程序
首先需要明白一个问题,就是 cocos 里面开发的 “退出”按钮
隶属于 cocos 项目,与 electron 毫无关系;但是关闭 exe
可执行程序呢,是 electron 的功能,与 cocos 毫无关系;
但是现在我的需求是要把 cocos 和 electron 关联起来。
所以我的方案是:想办法,在 cocos 点击关闭按钮的时候,由 cocos 向 electron 发送一个消息,当 electron 收到 cocos 传递过来的消息的时候,则由 electron 主动关闭 exe 窗口,这样就实现了点击按钮关闭功能。
上面的方案可行吗?非常可行,亲测可行!
方案
我使用的是 Electron 的 IPC (Inter-Process Communication) 机制,也就是 ipcMain
和 ipcRenderer
。
首先在cocos部分,写一个按钮,绑定一个点击事件,这个步骤我就不详细说了, 主要是这个点击事件里面是什么,也就是说怎么给 electron 发送消息:
// 关闭应用closeAppFunc() {window.ipcRenderer.send('close-app');}
其实就是上面这段代码,通过 ipcRenderer
,向 electron 发送一个 close-app
消息,当然 close-app
这个名字是自己起的,你叫啥都可以。
没了,这就是发送消息,window 是全局的,但是 window 上面其实是没有 ipcRenderer
的,先别急哈。
然后,就是修改 electron ,让它接收 cocos 发送过来的 close-app
消息。
首先我们在 electron 项目(electron-quick-start-exe)下面找到 main.js
文件,我们在 createWindow
方法里面,添加下面这段代码:
ipcMain.on('close-app', () => {mainWindow.close();app.quit()})
这段代码的意思就是接收到 close-app
消息之后关闭窗体,当然,ipcMain
找不到,我们需在文件开头引入一下子:
const { ipcMain } = require('electron');
好,这样 electron 就可以了。
但是,上面在 cocos 里面发送消息的时候说了, window
里面并没有 ipcRenderer
, 怎么办呢?没关系,我们在编译 cocos 文件之后,生成了一个 web-mobile
文件夹,在里面呢,有一个 index.html
文件,我们编辑这个文件,在他的 body 标签前面添加下面这段 js 代码:
<script type="text/javascript" >const { ipcRenderer } = require('electron');window.ipcRenderer = ipcRenderer;
</script>
OK,上面步骤完成之后,就可以打包了,打包完成就好使了!
注意,浏览器测试没用,必须打包成 exe 文件才可以用,浏览器测试会报错!!
electron 向 cocos 传递数据
上面说了一个通过 cocos 向 electron 传递数据,现在要说一下 electron 向 cocos 传递数据,啊哈哈哈哈!
为啥子说这个呢?因为我呢,还有一个需求,就是 打包后的 exe 可执行程序啊,需要读取当前文件夹下面的一个 json 文件,读取之后呢,需要在 cocos 程序中使用,你看这事儿闹的,这他妈的复杂,没关系,小意思!
方案
首先呢,我是这样想的,我在 cocos 一加载完啊,就给 electron 发送一个消息,告诉 electron 说,你得给我加载这个 json 文件啦!和上面的通信方式是一样的哈:
window.ipcRenderer.send('get-config');
你看,就一句代码,告诉 electron 给我加载文件!
然后 electron 收到 cocos 传递的消息之后呢,就可以加载这个 json 文件了,加载完文件之后,通过 reply
在把读取到的数据返回给 cocos :
ipcMain.on('get-config', (event) => {const p = path.resolve('./')// 读取当前文件加下 wjw.json 文件const resourcesPath = path.join(p, 'wjw.json');// 开始读文件fs.readFile(resourcesPath, 'utf8', (err, data) => { if (err) throw err; // 如果报错就抛出错误console.log(data); // 打印一下数据event.reply('wjw-data', data); // 把数据返回给 cocos});})
然后就简单了,cocos 里面接收一下就可以啦:
window.ipcRenderer.on('wjw-data', (event, data) => {// 把数据放进缓存cc.sys.localStorage.setItem('wjwData', data);// 从缓存里面读一下let value = cc.sys.localStorage.getItem('wjwData');// 打印一下缓存取出来的数据console.log('wjw-data 缓存读取的数据:', JSON.parse(value));
});
就这么简单!完成!
注意:依旧是需要打包测试,浏览器测试会报错哈!!谨记!