electron 如何申请 Mac 系统权限

ops/2025/1/21 5:40:52/

对于一些使用 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/ops/151840.html

相关文章

机器学习-基本术语

文章目录 1. **数据集&#xff08;Dataset&#xff09;**2. **样本&#xff08;Sample&#xff09;**3. **属性&#xff08;Attribute&#xff09;**4. **特征&#xff08;Feature&#xff09;**5. **属性值&#xff08;Attribute Value&#xff09;**6. **属性空间&#xff08…

如何爬取淘宝详情接口

在电商领域&#xff0c;淘宝作为中国最大的在线零售平台之一&#xff0c;拥有海量的商品数据。获取这些商品的详情信息对于市场分析、用户体验优化和商业决策具有重要意义。本文将详细介绍如何使用Python爬虫技术来爬取淘宝的详情接口数据&#xff0c;包括环境搭建、基本爬虫编…

HTML5 教程(下)

HTML5 Video(视频) HTML5 Video(视频) 在本节内容中&#xff0c;你将了解到在HTML5中视频是如何工作的、主流浏览器支持的视频格式以及如何对网页中的视频进行控制。 很多站点都会使用到视频. HTML5 提供了展示视频的标准。 检测您的浏览器是否支持 HTML5 视频&#xff1a; …

IP归属地为什么和定位不一致?原因解析

在数字化时代&#xff0c;IP地址作为网络设备的唯一标识符&#xff0c;不仅关乎设备间的通信&#xff0c;还涉及到用户的网络身份与位置信息。其中&#xff0c;IP归属地作为IP地址的地理位置信息&#xff0c;备受用户关注。然而&#xff0c;在日常使用中&#xff0c;不少用户会…

后端开发流程学习笔记

后端开发流程学习笔记 术语前瞻 分类英文中文解释研发模式Waterfall Model瀑布模型瀑布模型&#xff08;Waterfall Model&#xff09;最早强调软件或系统开发应有完整之周期&#xff0c;且必须完整的经历周期之每一开发阶段&#xff0c;并系统化的考量分析与设计的技术、时间…

探秘 JMeter 前置处理器:让性能测试如虎添翼

想象一下&#xff0c;你是一位超级英雄&#xff0c;要对一个庞大的虚拟城市&#xff08;Web 应用&#xff09;进行全面的 “健康检查”。JMeter 就是你的神奇工具包&#xff0c;而其中的前置处理器&#xff0c;就像是这个工具包里的各种超级武器&#xff0c;能帮助你轻松应对各…

网络安全VS数据安全

关于网络安全和数据安全&#xff0c;我们常听到如下两种不同声音&#xff1a; 观点一&#xff1a;网络安全是数据安全的基础&#xff0c;把当年做网络安全的那一套用数据安全再做一遍。 观点二&#xff1a;数据安全如今普遍以为是网络安全的延伸&#xff0c;实际情况是忽略数据…

前端Vue框架——npm ci与npm install的区别以及package-lock.json文件与package.json的区别

目录 一、npm ci与npm install的区别 &#xff08;一&#xff09;npm ci 的作用 &#xff08;二&#xff09;与 npm install 的区别 二、package-lock.json文件与package.json的区别 1️⃣ package.json 2️⃣ package-lock.json 3️⃣ 区别对比 4️⃣ 使用建议 5️⃣…