electron 如何申请 Mac 系统权限

server/2025/1/21 2:02:36/

对于一些使用 Electron开发的app, 需要获取一些系统权限,比如录屏权限, 获取摄像头权限,麦克风等等,类似于以下界面:

在这里插入图片描述

那么Electron App 应该如何申请呢?
首先我们明确一下macOS中基础权限的分类,可以分为以下几种:

  1. 隐私权限(Private Permissions) :
<!-- entitlements.mac.plist -->
<dict><!-- 摄像头 --><key>com.apple.security.device.camera</key><true/><!-- 麦克风 --><key>com.apple.security.device.microphone</key><true/><!-- 位置信息 --><key>com.apple.security.personal-information.location</key><true/><!-- 通讯录 --><key>com.apple.security.personal-information.addressbook</key><true/><!-- 日历 --><key>com.apple.security.personal-information.calendars</key><true/><!-- 照片 --><key>com.apple.security.personal-information.photos-library</key><true/><!-- 屏幕录制 --><key>com.apple.security.screen-recording</key><true/><!-- 辅助功能 --><key>com.apple.security.automation.apple-events</key><true/>
</dict>
  1. 系统功能权限
<dict><!-- 网络访问 --><key>com.apple.security.network.client</key><true/><!-- 作为服务器接收连接 --><key>com.apple.security.network.server</key><true/><!-- 文件访问 --><key>com.apple.security.files.user-selected.read-write</key><true/><!-- USB访问 --><key>com.apple.security.device.usb</key><true/><!-- 蓝牙访问 --><key>com.apple.security.device.bluetooth</key><true/><!-- 打印权限 --><key>com.apple.security.print</key><true/>
</dict>
  1. App Sandbox 相关权限:
<dict><!-- 启用沙箱 --><key>com.apple.security.app-sandbox</key><true/><!-- 读取下载文件夹 --><key>com.apple.security.files.downloads.read-write</key><true/><!-- 读写用户选择的文件 --><key>com.apple.security.files.user-selected.read-write</key><true/><!-- 读写图片文件夹 --><key>com.apple.security.files.pictures.read-write</key><true/><!-- 读写音乐文件夹 --><key>com.apple.security.files.music.read-write</key><true/>
</dict>
  1. 硬件权限
<dict><!-- 音频输入 --><key>com.apple.security.device.audio-input</key><true/><!-- HID设备访问 --><key>com.apple.security.device.usb</key><true/><!-- 打印机访问 --><key>com.apple.security.print</key><true/>
</dict>

那么基础权限请求方式为:

javascript">const { systemPreferences } = require('electron')// 检查和请求屏幕录制权限
async function requestScreenCapture() {// 检查权限状态const status = systemPreferences.getMediaAccessStatus('screen')if (status !== 'granted') {// 请求权限const granted = await systemPreferences.askForMediaAccess('screen')return granted}return true
}

辅助权限的请求方式为:

javascript">const { app } = require('electron')// 检查辅助功能权限
function checkAccessibilityPermission() {return systemPreferences.isTrustedAccessibilityClient(false)
}// 请求辅助功能权限
function requestAccessibilityPermission() {return systemPreferences.isTrustedAccessibilityClient(true)
}

完善的权限管理类为:

javascript">class MacPermissions {constructor() {this.systemPreferences = require('electron').systemPreferences}async checkPermission(type) {switch(type) {case 'screen':return this.systemPreferences.getMediaAccessStatus('screen')case 'camera':return this.systemPreferences.getMediaAccessStatus('camera')case 'microphone':return this.systemPreferences.getMediaAccessStatus('microphone')case 'accessibility':return this.systemPreferences.isTrustedAccessibilityClient(false)}}async requestPermission(type) {try {switch(type) {case 'screen':case 'camera':case 'microphone':return await this.systemPreferences.askForMediaAccess(type)case 'accessibility':return this.systemPreferences.isTrustedAccessibilityClient(true)}} catch(error) {console.error(`Error requesting ${type} permission:`, error)return false}}
}

同时需要一个build文件夹,文件夹地址与dist同级别:
在这里插入图片描述
在 build文件夹中, 需要一个 entitlements.mac.plist文件,文件中需要声明所需要的权限:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict><!-- 屏幕录制权限 --><key>com.apple.security.screen-recording</key><true/><!-- 辅助功能权限 --><key>com.apple.security.automation.apple-events</key><true/><!-- 摄像头访问权限 --><key>com.apple.security.device.camera</key><true/><!-- 麦克风访问权限 --><key>com.apple.security.device.microphone</key><true/><!-- 照片库访问权限 --><key>com.apple.security.personal-information.photos-library</key><true/><!-- 位置信息访问权限 --><key>com.apple.security.personal-information.location</key><true/>
</dict>
</plist>

配置好之后, 需要在 package.json中配置mac的属性:

{"build": {"mac": {"hardenedRuntime": true,"entitlements": "build/entitlements.mac.plist","entitlementsInherit": "build/entitlements.mac.plist"}}
}

在打包时, electron-builder 会自动将这些权限配置应用到最终的应用程序中。

然后再App启动时,可以使用代码控制权限申请,会得到类似的对话框:

在这里插入图片描述

然后点击系统设置,即可跳转到系统界面,点击手动打开相应的权限,即可完成系统权限的设置.

备注:

那么哪些权限需要我们手动申请呢(可以通过代码开启)?

  1. 媒体权限
javascript">const { systemPreferences } = require('electron')// 摄像头
await systemPreferences.askForMediaAccess('camera')// 麦克风
await systemPreferences.askForMediaAccess('microphone')// 屏幕录制
// 注意:屏幕录制权限需要用户在系统设置中手动授权
systemPreferences.getMediaAccessStatus('screen')
  1. 通知权限
javascript">const { Notification } = require('electron')// 请求通知权限
async function requestNotificationPermission() {if (!Notification.isSupported()) return falseconst permission = await Notification.requestPermission()return permission === 'granted'
}
  1. 辅助功能权限
javascript">const { systemPreferences } = require('electron')// 检查辅助功能权限
systemPreferences.isTrustedAccessibilityClient(false)

以下权限需要用户在系统设置中手动开启(无法通过代码直接请求):

文件系统权限:

  • 访问Documents、Desktop、Downloads等目录
  • 访问照片库
  • 访问通讯录
  • 访问日历
  • 访问提醒事项

系统权限:

  • 屏幕录制
  • 辅助功能
  • 完全磁盘访问权限
  • 自动化权限

那么如何引导用户开启呢?

javascript">
const { dialog, shell } = require('electron')class PermissionGuide {static async showSettingsGuide(permissionType) {const guides = {screen: {title: '需要屏幕录制权限',message: '请在系统设置中允许屏幕录制权限',prefPane: 'Privacy_ScreenCapture'},photos: {title: '需要照片访问权限',message: '请在系统设置中允许照片访问权限',prefPane: 'Privacy_Photos'},files: {title: '需要文件访问权限',message: '请在系统设置中允许文件访问权限',prefPane: 'Privacy_FilesAndFolders'},accessibility: {title: '需要辅助功能权限',message: '请在系统设置中允许辅助功能权限',prefPane: 'Privacy_Accessibility'}}const guide = guides[permissionType]if (!guide) returnconst result = await dialog.showMessageBox({type: 'info',title: guide.title,message: guide.message,buttons: ['打开系统设置', '取消']})if (result.response === 0) {// 打开系统设置对应页面shell.openExternal(`x-apple.systempreferences:com.apple.preference.security?${guide.prefPane}`)}}
}// 完整的权限管理类
class PermissionManager {// 检查需要手动申请的权限async checkMediaPermission(type) {const status = await systemPreferences.getMediaAccessStatus(type)if (status === 'not-determined') {return await systemPreferences.askForMediaAccess(type)}return status === 'granted'}// 检查需要手动开启的权限async checkSystemPermission(type) {let status = falseswitch(type) {case 'screen':status = systemPreferences.getMediaAccessStatus('screen') === 'granted'breakcase 'accessibility':status = systemPreferences.isTrustedAccessibilityClient(false)break// 其他系统权限检查...}if (!status) {await PermissionGuide.showSettingsGuide(type)}return status}// 权限检查和请求的统一接口async ensurePermission(type) {// 需要手动申请的权限if (['camera', 'microphone'].includes(type)) {return await this.checkMediaPermission(type)}// 需要在系统设置中手动开启的权限if (['screen', 'accessibility', 'photos', 'files'].includes(type)) {return await this.checkSystemPermission(type)}return false}
}// 使用示例
async function example() {const permissionManager = new PermissionManager()// 检查和请求摄像头权限const hasCameraPermission = await permissionManager.ensurePermission('camera')if (!hasCameraPermission) {console.log('未获得摄像头权限')return}// 检查屏幕录制权限const hasScreenPermission = await permissionManager.ensurePermission('screen')if (!hasScreenPermission) {console.log('未获得屏幕录制权限')return}// 正常执行需要权限的功能...
}

http://www.ppmy.cn/server/160050.html

相关文章

Linux操作命令之云计算基础命令

一、图形化界面/文本模式 ctrlaltF2-6 图形切换到文本 ctrlalt 鼠标跳出虚拟机 ctrlaltF1 文本切换到图形 shift ctrl "" 扩大 ctrl "-" 缩小 shift ctrl "n" 新终端 shift ctrl "t" 新标签 alt 1,…

Vue3初学之Element-plus Form表单

1.使用 el-form 组件 el-form 是一个表单容器&#xff0c;可以包含多个 el-form-item&#xff0c;每个 el-form-item 包裹具体的表单控件&#xff0c;如输入框、选择器、日期选择器等。 <template><el-form :model"form" label-width"120px">…

PyTorch使用教程(2)-torch包

1、简介 torch包是PyTorch框架最外层的包&#xff0c;主要是包含了张量的创建和基本操作、随机数生成器、序列化、局部梯度操作的上下文管理器等等&#xff0c;内容很多。我们基础学习的时候&#xff0c;只有关注张量的创建、序列化&#xff0c;随机数、张量的数学数学计算等常…

C语言笔记——第二章 顺序结构程序设计(三)

2.3 数据输出 一、字符型输出函数&#xff08;putchar&#xff09; 1、函数&#xff1a;putchar(c) 参数&#xff1a;c为字符常量&#xff0c;变量或表达式 功能&#xff1a;把参数c输出到显示器上 2、当c为被一个单引号引起的字符时&#xff0c;则输出该字符 #include&l…

AAPM:基于大型语言模型代理的资产定价模型,夏普比率提高9.6%

“AAPM: Large Language Model Agent-based Asset Pricing Models” 论文地址&#xff1a;https://arxiv.org/pdf/2409.17266v1 Github地址&#xff1a;https://github.com/chengjunyan1/AAPM 摘要 这篇文章介绍了一种利用LLM代理的资产定价模型&#xff08;AAPM&#xff09;…

深入了解卷积神经网络(CNN):图像处理与深度学习的革命性技术

深入了解卷积神经网络&#xff08;CNN&#xff09;&#xff1a;图像处理与深度学习的革命性技术 导语 卷积神经网络&#xff08;CNN&#xff09;是现代深度学习领域中最重要的模型之一&#xff0c;特别在计算机视觉&#xff08;CV&#xff09;领域具有革命性的影响。无论是图…

Redisson发布订阅学习

介绍 Redisson 的消息订阅功能遵循 Redis 的发布/订阅模式&#xff0c;该模式包括以下几个核心概念&#xff1a; 发布者&#xff08;Publisher&#xff09;&#xff1a;发送消息到特定频道的客户端。在 Redis 中&#xff0c;这通过 PUBLISH 命令实现。 订阅者&#xff08;Sub…

SAP POC 项目完工进度 - 收入确认方式【工程制造行业】【新准则下工程项目收入确认】

1. SAP POC收入确认基础概念 1.1 定义与原则 SAP POC&#xff08;Percentage of Completion&#xff09;收入确认方式是一种基于项目完工进度来确认收入的方法。其核心原则是根据项目实际完成的工作量或成本投入占预计总工作量或总成本的比例&#xff0c;来确定当期应确认的收…