Electron快速入门,聊聊跨进程通信那些事儿

发表于 3年以前  | 总阅读数:541 次

前言

有句话叫做“有需求就有市场”,技术领域也同样是如此。在过往的前端领域之上,当面临需要涉及操作系统的时候,前端coder往往显得力不从心。这便是桌面应用的需求造就了 Electron 的到来。

什么是Electron?

简介

打开官网,我们便可以看到其介绍,使用 JavaScript,HTML 和 CSS 构建跨平台的桌面应用程序。顾名思义,我们可以完全自主控制地去构建跨平台桌面应用了,无需强依赖于桌面应用原生开发人员,有效降低沟通成本,再也不用求爷爷告奶奶去协调资源,完全可以自主访问以往受限的操作系统相关底层API。

当然,这也并不意味着百利而无一害,毕竟获得更多 power 的同时,也会承担更多 Risk。

优秀应用

  • Visual Studio Code
  • Atom
  • Postman
  • 社交通讯 WhatsApp
  • MongoDB 桌面管理工具 Compass
  • 接口管理工具 Apifox
  • ... ...

技术选型

Electron核心组成

Electron 是基于 ChromiumNode 实现的,才使得我们可以无缝轻松使用其开发跨平台桌面应用,降低了学习门槛,更加轻松上手开发。

为了弥补前端访问系统API方面的不足,Electron 内部对系统API进行了封装,相关譬如系统对话框、系统托盘、系统菜单、剪切板等。而其他诸如网络访问控制、本地文件系统等则由 Node 提供底层支持。

Electron 通过各操作系统之间的消息循环打通 Node 和 Chromium 的事件循环,保证了其两者的松耦合。进而推出了主进程渲染进程的概念。

Electron 起了一个新到安全线程去轮询, 当 Nodejs 有新的事件之后,通过 PostTask 转发到 Chromiums 的事件循环当中,完成 Electron 的事件融合

具体相关源码:https://github.com/electron/electron/blob/main/shell/common/node_bindings.cc

Electron 工作机制

啥也不说,先上个图

左侧是我们传统开发中前端人员所能控制展示的区域,而当基于 Electron 去开发桌面应用时,我们可控区域如右侧所示,全部交由前端自主开发。

而 Electron 开发中,页面不再是用户手动输入打开,而是开发着自主硬编码好的。

Electron应用程序主要分为主进程渲染进程两个部分,即对应着右侧图中上下两个部分。

进程

一个 Electron 应用程序由一个主进程(有且只有一个) + 多个渲染进程组成。

主进程

功能:桥梁作用,连接操作系统和渲染进程,负责管理所有窗口及其对应的渲染进程。

  • 有且只有一个,整个应用入口
  • 创建、管理渲染进程
  • 控制应用生命周期
  • 使用 NodeJS 特性
  • 调用操作系统 API
  • ...

渲染进程

功能:负责完成渲染页面、接收用户输入、相应用户交互等工作。

  • 渲染页面
  • 使用部分 Electron 模块 API
  • 使用 NodeJS 特性
  • 一个应用可存在多个渲染进程
  • 控制用户交互逻辑
  • 访问 Dom API

核心模块归属情况

上图为笔者整理的常用模块归属情况,详细主进程、渲染进程会在后续的实战部分进行部分讲解。

IPC 通信

大概了解完两个进程的功能之后,我们接下去该考虑一下这两者之间,是如何进行协调通信的。

Electron 中通过提供ipcMain、ipcRenderer来作为主进程、渲染进程之间的通信桥梁。

从接口定义中不难推断出其管道IPC是通过继承 EventEmitter 来实现IpcMain、IpcRenderer,并拓展了其他工具类方法。纵使翻阅 electron 源码也是如此,感兴趣的同学可以自己去研究研究,这里只做简单了解。

讲到这里,对于主进程和渲染进程的通信就变得十分容易理解了,通过管道IPC,采用熟知的发布订阅模式进行两者之间的通信。

窗口获取

  • BrowserWindow.getFocusedWindow(): 获取当前激活状态窗口
  • remote.getCurrentWindow(): 获取当前渲染进程关联窗口
  • BrowserWindow.fromI(id): 根据id获取窗口实例
  • BrowserWindow.getAllWindow(): 获取所有窗口

remote

在讲实际项目基本操作之前,先介绍一下一个比较特殊的 remote 模块

remote:这是一个 Electron 内部的模块,渲染进程可以通过此模块访问到主进程的模块、对象和方法。包括在渲染进程创建窗口、创建菜单等类似本应该由主进程完成的操作通过 remote 依然可以在渲染进程进行完成。前提是创建窗口的时候,开启了 nodeIntegration 配置,让渲染进程有能力去访问 Node.js 相关API。但是其背后的机制是一样的,通过通知主进程,主进程接收消息后再进行相关操作,然后把相关的实例以远程对象形式返回到渲染进程。

局限性

当然,remote虽然极大便利了开发者,但是也带来了一些局限性

  • 性能损耗大:跨进程操作
  • 制造混乱:异步导致执行顺序错乱
  • 制造假象:代理对象导致数据混乱
  • 安全问题:恶意代码攻击

在不久的将来,remote 模块将从 electron 内部移除,但是还很漫长,保持关注即可。

实战

从这里开始,我们将从实际的项目基本功能演练进行相关核心模块的使用演示。

进程互访

渲染进程TO主进程

其核心原理是因为暴露了 remote 模块,让开发者可以相对随心所欲的进行访问。

比如我们在主进程里想要获取应用程序的程序路径,我们可以在主进程这么获取:

import { app } from 'electron'
//  获取应用程序路径
const ROOT_PATH = app.getAppPath()

而在渲染进程中,有了 remote 模块,此类简单属性获取也变得更加方便:

const { app } = require('electron').remote
//  获取应用程序路径
const ROOT_PATH = app.getAppPath()

然鹅,其不仅可以访问主进程的属性,还可以调用相关方法,再举个栗子:

const { remote } = require('electron')
//  渲染进程打开开发者工具
remote.getCurrentWindow().webContents.openDevTools()

结论:通过 remote 模块,我们可以方便的访问主进程的模块、对象和方法。

主进程TO渲染进程

渲染进程是由主进程控制的,通过创建的渲染进程的窗口win.webContents对象,可以轻易地访问渲染进程相关内容。

这里官网的相关事例说明相对完善,可以自行查看。

const {BrowserWindow} = require('electron')
let win = new BrowserWindow({width: 800, height: 600})
win.loadURL('http://github.com')
//  获取当前网页窗口的网址
let currentURL = win.webContents.getURL()

进程通信

其核心即为管道IPC通信,上文有所说明,不再赘述。

主进程TO渲染进程

主要有两种方式进行通信:

  • ipcMain 接收渲染进程消息
  • webContents 发送给渲染进程

比方说呢,项目里我有一个地方需要监听用户通过 a 标签打开外链,但是我又不想它重新创建一个窗口,所以需要系统干预进行处理。

我的解决方案就是通过 进程通信 + shell 模块来通过系统默认浏览器来打开目标链接。

<a href="www.baidu.com" target="_blank">百度</a>
const { ipcMain, shell } = require('electron');
ipcMain.on('open-url', (event, url) => {
  //  'open-url' 为管道消息名称
  //  event 为消息发送相关信息 
  //  event.sender 为渲染进程的webContents对象事例
  //  url 为传递参数

  //  通过系统默认浏览器打开目标外链
  shell.openExternal(url)
})

如果此时到这里之后,我们想告诉渲染进程我们已经成功接收并执行了,也就是回调,那么我们就可以通过渲染进程事例进行对渲染进程消息通知:

方法1: webContents 直接回传

const { ipcMain, shell } = require('electron');
const win = new BrowserWindow({
  //... ...
})
ipcMain.on('open-url', (event, url) => {
  //  ... ...
  //  通过系统默认浏览器打开目标外链
  shell.openExternal(url)
  //  向渲染进程进行消息通知
  win.webContents.send('ready-open-url')
})

方法2: ipcMain.on 接收消息通知时,event.sender 为渲染进程的webContents 对象事例,我们也可以直接进行消息通知:

const { ipcMain, shell } = require('electron');
const win = new BrowserWindow({
  //... ...
})
ipcMain.on('open-url', (event, url) => {
  //  ... ...
  //  通过系统默认浏览器打开目标外链
  shell.openExternal(url)
  //  向渲染进程进行消息通知
  event.sender.send('ready-open-url')
})

方法3: ipcMain.on 接收消息通知时,event 提供reply方法,相应消息给来源渲染进程,本质上与方法2逻辑一致。

//  ... ... 
ipcMain.on('open-url', (event, url) => {
  //  ... ...
  //  通过系统默认浏览器打开目标外链
  shell.openExternal(url)
  //  向渲染进程进行消息通知
  event.replay('ready-open-url')
})

渲染进程TO主进程

主要是通过 ipcRenderer 模块进行向主进程进行消息通知。

还是拿上面的例子来说,打开外链,那么我们就需要在渲染进程中进行向主进程通知,我需要打开某个外链。具体如下:

本事例为在 Vue 中的实践

const { ipcRenderer } = require('electron')
const links = document.querySelectorAll('a[href]')
links.forEach(link => {
  link.addEventListener('click', e => {
    const url = link.getAttribute('href')
    e.preventDefault()
    ipcRenderer.send('open-url', url)
  })
})

当然这是一个异步的消息队列~ 可能在某些需求场景下,我们需要传递的是同步消息, 那么我们只要在主进程里直接设置 returnValue 的值即可,而渲染进程不需要再重复监听。

还是拿上面的打开外链做个演示说明:

//  主进程
ipcMain.on('open-url', (event, url) => {
  //  通过系统默认浏览器打开目标外链
  shell.openExternal(url);
  //  设置返回值
  event.returnValue = 'success';
})

//  渲染进程
const returnVal = ipcRenderer.sendSync('open-url', url);
console.log(returnVal) // success

当然,同步通信会阻塞渲染进程,孰轻孰重需要谨慎选择~

渲染进程TO渲染进程

当我们程序相对复杂,创建了多个渲染进程的时候,就容易出现多个渲染进程之间相互通信的场景。

解决方案其实也是显而易见的,既然是一个爹(主进程)生的,那么直接通过主进程进行一个过渡中转,就可以实现双方的一个通信了。毕竟窗口的创建往往就是在主进程里完成的,其持有所有窗口的实例,只要拿到目标窗口的id即可进行通信。

每个窗口 webContents.getProcessId() 或者 webContents.id 即可获得对应窗口的id。

伪代码如下:

//  win1窗口发送消息
ipcRenderer.sendTo(win2.webContents.id, 'send-msg', params1, params2)

//  win2窗口接收消息
ipcRenderer.on('send-msg', (event, params1, params2) => {
  //  ... ...
})

其中 ipcRenderer.sendTo 中,第一个参数为目标窗口id,第二个参数为管道消息名称,其余为传递参数。

当然,需要发送消息给到的目标窗口是打开的状态,否则可就接受不到了。

到此,三种场景的进程通信介绍完毕了。

有个小注意事项⚠️需要关注一下:

进程之间的通信过程中,发送的json对象都会被序列化和反序列化,所以传递的时候需要注意其方法和原型链上的数据是不会被传递的。

这一点,跟小程序 setData 进行视图层和逻辑层数据传输是十分类似的,evaluteJavascript 所实现的,最终都转化为字符串传递。

搭建开发环境

electron的安装,兴许是一个漫长的过程,这里强烈建议大家有条件的话能够科学上网,可以省掉不少破事。当然没有的话,也没关系(假的),我们也有解决方案。

包管理工具的话,大家就各自选择了,npm/yarn 都可以,这里以 yarn 进行说明。

初始化项目

yarn init

electron 依赖包有点大,默认从github下载,所以巨艰难。设置镜像

yarn config set set ELECTRON_MIRROR=http://npm.taobao.org/mirrors/electron/

全局安装 electron

yarn global add electron

这是正常安装成功 node_modules/electron 里应有的文件结构,如果后续运行报错了,大概率就是安装失败了。

可以选择手工操作处理此类问题,如果你上网不够科学的话~

解决方案:

  • /node_modules/electron/ 目录下创建path.txt

  • win输入:electron.exe

  • mac输入:Electron.app/Contents/MacOS/Electron

  • /node_modules/electron/ 目录下创建dist目录

  • 版本包地址 下找到对应版本解压到dist目录

至此,electron 安装就算是成功了。

package.json 中配置“main” 入口文件即 electron 的启动文件,即主进程的相关代码。

下面贴一个以 Vue 框架进行开发的项目文件结构图。

引入现代框架

通过引用模板项目即可快速入手开发,一个字-香!

Angular

  • 官方维护版本:https://github.com/angular/angular-electron (缺点:停更许久)
  • 社区活跃版本:https://github.com/maximegris/angular-electron

React

  • electron-react-boilerplate该项目模板汇集了 Electron、React、Redux、React Router、webpack、React Hot Loader等,对入手尝鲜 Electron 来说,简直是不要太香。

Vue

  • Vue CLI Plugin Electron Builder:https://github.com/nklayman/vue-cli-plugin-eletron-builder
  • electron-vue: https://github.com/SimulatedGREG/electron-vue (也已基本停更)

通过引用前端三剑客框架,我们就可以快速投入到 Electron 的GUI应用开发之中,当然如果你执着于 jQuery,也是可以引用开发的,只是不建议而已,这就涉及到 Electron 性能相关了,这里不再展开。

发布打包

设置图标

  • 准备一张1024*1024尺寸的png图 放在public下
  • 安装 electron-icon-builder 插件
yarn add electron-icon-builder --dev

容易安装失败 多装几次(科学上网)

  • package.json 添加指令配置
"build-icon": "electron-icon-builder --input=./public/logo.png --output=build --flatten"
  • 执行
yarn build-icon

生成应用图标到对应的build文件夹

打包安装包

yarn electron:build

直到 Done 出来之后也就大功告成了~

一个 electron 应用也就生成好了。

核心模块演示

设置全局变量

项目开发中,经常有个需求便是主题换肤,在尝试过程中自然就想到了 mac 下的系统主题切换。由此来演示下如何设置全局变量,并在渲染进行获取。

主进程

import { nativeTheme } from 'electron' 
/** 添加全局属性 * */
global.selfConfigs = {
  nativeTheme: () => nativeTheme.shouldUseDarkColors
}

渲染进程

const nativeTheme = require('electron').remote.getGlobal('selfConfigs').nativeTheme()

当然,直接通过 remote 调用 nativeTheme 也是可以的,just a 栗子。

脚本注入

  • 通过 preload 配置项,进行脚本注入
let win = new BrowserWindow({
  webPreferences: {
    preload: jsFilePath,
    nodeIntegration: true
  }
})
  • 通过 executeJavaScript 注入脚本

比方说,在 window 上添加自定义属性

主进程

let win = new BrowserWindow({
  //  ...
})
win.webContents.executeJavaScript(`
  window.onlyConfig = {a:1,b:2}
`)

渲染进程

console.log(window.onlyConfig) //  {a:1,b:2}

实现系统消息通知

有两种可实现方式,两种方式的使用方法区别不大。

  • HTML API 发送消息通知,缺点就是需要用户授权同意之后
  • 主进程直接发送系统消息
    const { Notification } = this.$electron.remote
    const notification = new Notification({
      title: '新建通知', BVVv    body: '您新建了一个md文档,请点击查看'
    })
    notification.show()
    notification.on('click', () => {})

实现系统托盘及相关菜单

系统托盘由 Tray 模块提供,用于添加托盘图标和上下文菜单至通知栏。

啥也不说了,先上大头贴

实现原理相对简单,通过定时器刷新托盘图标,并添加相对应的上下文菜单进行逻辑操作即可,更多功能可以自行DIY。

/** 添加系统托盘 * */
  let toggleSwitch = true; let toggleFlag = false; let timer
  const icon1 = path.join(__dirname, '../public/icon.png')
  const icon2 = path.join(__dirname, '../public/icon2.png')
  tray = new Tray(icon1)
  tray.setToolTip('Electron 系统托盘')
  tray.on('click', () => {
    console.log('托盘单击')
    win.isVisible() ? win.hide() : win.show()
  })
  tray.on('right-click', () => {
    const menuConfig = Menu.buildFromTemplate([
      {
        label: toggleSwitch ? '开启闪烁图标' : '关闭闪烁图标',
        click: () => {
          if (toggleSwitch) {
            timer = setInterval(() => {
              if (toggleFlag) {
                tray.setImage(icon2)
              } else {
                tray.setImage(icon1)
              }
              toggleFlag = !toggleFlag
            }, 600)
          } else {
            tray.setImage(icon1)
            clearInterval(timer)
          }
          toggleSwitch = !toggleSwitch
        }
      },
      {
        label: '退出',
        click: () => app.quit()
      }
    ])
    tray.popUpContextMenu(menuConfig)
  })
  /** 添加系统托盘 * */

实现系统右键菜单

以往,我们处理的思路是根据用户右键所在鼠标坐标生成一个右键菜单,相对麻烦并且还需要考虑边界状态。好比如编写此篇文章所用到的 mdnice ,即是用此方案使用了自定义右键菜单。

通过 electron 暴露的 screen 模块,获取到当前鼠标所在位置

window.oncontextmenu = () => {
  const point = require('electron').screen.getCursorScreenPoint();
}

而在 electron 里,我们可以直接自定义系统右键菜单,兼容性更佳。

//  监听右键菜单触发
  win.webContents.on('context-menu', (event, params) => {
    const selectEnabled = !!params.selectionText.trim().length
    const template = [
      {
        label: '为当前页面生成二维码',
        click: () => {
          console.log(`当前页面地址为:${params.pageURL}`)
        }
      }
    ]
    if (selectEnabled) {
      template.unshift(...[{
        label: '复制',
        role: 'copy',
        visible: () => !selectEnabled
      },
      {
        label: '剪切',
        role: 'cut'
      }])
    }
    const RightMenu = Menu.buildFromTemplate(template)
    RightMenu.popup()
  })

最终实现如下基础效果:

常见问题

npm 安装electron不成功

解决方案:通过cnpm淘宝镜像安装 避免安装失败

报错 require is not defined

原因:electron12以后默认没法在渲染进程中引入Nodejs模块

解决方案:

找到 ./background.js里的 new BrowserWindow 添加配置项 nodeIntegration 设置为 true

导入electron.remote后,提示undefined

原因: 在electron10版本之后,remote默认关闭,需要手动开启

解决方案:

找到 ./background.js里的 new BrowserWindow 添加配置项

const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      enableRemoteModule: true, // 解决remote为undefined问题
      nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION
    }
  })

mac 下快捷键失效的问题

发现在mac下,本该熟练的复制、剪切、粘贴等快捷失效了。你说说,作为一名合格的 CV 工程师,这你能忍?

这时候就想起尤大的表情包,看文档!

马不停蹄一股脑加了段代码,瞬间感觉牛逼哄哄

  // 判断 mac 下 注册快捷键
  if (process.platform === 'darwin') {
    const contents = win.webContents
    globalShortcut.register('CommandOrControl+C', () => {
      contents.copy()
    })
    globalShortcut.register('CommandOrControl+V', () => {
      contents.paste()
    })
  }

后面发现这个方案并不是有效的解决方案,注册完快捷键后发现 electron 占据了系统的原有快捷键,这才发现除了 electron 以外的其他应用,这些快捷键都失效了~

后面仔细研究一番之后,通过判断应用是否激活状态,来进行相关快捷键的注册/注销.

//  处理系统本身的快捷键 复制 全选 等
  win.on('focus', () => {
    // mac下快捷键失效的问题
    if (process.platform === 'darwin') {
      globalShortcut.register('CommandOrControl+C', () => {
        console.log('注册复制快捷键成功')
        contents.copy()
      })
      globalShortcut.register('CommandOrControl+V', () => {
        console.log('注册粘贴快捷键成功')
        contents.paste()
      })
      globalShortcut.register('CommandOrControl+X', () => {
        console.log('注册剪切快捷键成功')
        contents.cut()
      })
      globalShortcut.register('CommandOrControl+A', () => {
        console.log('注册全选快捷键成功')
        contents.selectAll()
      })
    }
  })
  win.on('blur', () => {
    globalShortcut.unregister('CommandOrControl+C') // 注销键盘事件
    globalShortcut.unregister('CommandOrControl+V') // 注销键盘事件
    globalShortcut.unregister('CommandOrControl+X') // 注销键盘事件
    globalShortcut.unregister('CommandOrControl+A') // 注销键盘事件
  })

windows 下控制台出现中文乱码

常见的gb2312为936 utf8为65001 配置执行命令即可解决

"start": "chcp 65001 && electron ."

Vue 构建的 history 模式项目打包空白

history 模式匹配不到对应静态资源,需要做一层处理,或者router 的 mode 切换为 hash 即可。

总结

electron 优势

  • 上手门槛低
  • 开发周期短

electron 不足

  • 打包后应用体积过大
  • 版本发布过快
  • 安全性问题
  • 资源消耗较大
  • 平台上架难

前端想象力

  • 无浏览器兼容问题
  • 支持 ES 高级语法
  • 无跨域问题
  • 支持 Node.js

参考

  • electron官网
  • 《Electron实战(入门、进阶与性能优化)》
  • 掘金小册 - 《Electron + React 从 0 到 1 实现简历平台实战》

本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/-SkNURk7OTqc7O7g1hhwRg

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237287次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8122次阅读
 目录