electron 如何申请 Mac 系统权限

对于一些使用 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>

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

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
}

辅助权限的请求方式为:

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

完善的权限管理类为:

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

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

文件系统权限:

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

系统权限:

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

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


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.rhkb.cn/news/2344.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浅谈云计算02 | 云计算模式的演进

云计算计算模式的演进 一、云计算计算模式的起源追溯1.2 个人计算机与桌面计算 二、云计算计算模式的发展阶段2.1 效用计算的出现2.2 客户机/服务器模式2.3 集群计算2.4 服务计算2.5 分布式计算2.6 网格计算 三、云计算计算模式的成熟与多元化3.1 主流云计算服务模式的确立3.1.…

An FPGA-based SoC System——RISC-V On PYNQ项目复现

本文参考&#xff1a; &#x1f449; 1️⃣ 原始工程 &#x1f449; 2️⃣ 原始工程复现教程 &#x1f449; 3️⃣ RISCV工具链安装教程 1.准备工作 &#x1f447;下面以LOCATION代表本地源存储库的安装目录&#xff0c;以home/xilinx代表在PYNQ-Z2开发板上的目录 ❗ 下载Vivad…

AI智能体实战|使用扣子Coze搭建AI智能体,看这一篇就够了(新手必读)

有朋友看到我使用Coze搭建的AI智能体蛮实用的&#xff0c;也想自己尝试一下。那今天我就分享一下如何使用Coze&#xff08;扣子&#xff09;搭建AI智能体&#xff0c;手把手教学&#xff0c;流程超级详细&#xff0c;学会了的话&#xff0c;欢迎分享转发&#xff01; 一、搭建A…

.NET8.0多线程编码结合异步编码示例

1、创建一个.NET8.0控制台项目来演示多线程的应用 2、快速创建一个线程 3、多次运行程序&#xff0c;可以得到输出结果 这就是多线程的特点 - 当多个线程并行执行时&#xff0c;它们的具体执行顺序是不确定的&#xff0c;除非我们使用同步机制&#xff08;如 lock、信号量等&am…

nginx 实现 正向代理、反向代理 、SSL(证书配置)、负载均衡 、虚拟域名 ,使用其他中间件监控

我们可以详细地配置 Nginx 来实现正向代理、反向代理、SSL、负载均衡和虚拟域名。同时&#xff0c;我会介绍如何使用一些中间件来监控 Nginx 的状态和性能。 1. 安装 Nginx 如果你还没有安装 Nginx&#xff0c;可以通过以下命令进行安装&#xff08;以 Ubuntu 为例&#xff0…

《数据思维》之数据可视化_读书笔记

文章目录 系列文章目录前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 数据之道&#xff0c;路漫漫其修远兮&#xff0c;吾将上下而求索。 一、数据可视化 最基础的数据可视化方法就是统计图。一个好的统计图应该满足四个标准&#xff1a;准确、有…

Linux之进程

Linux之进程 一.进程进程之形ps命令进程状态特殊进程孤儿进程守护进程 进程创建之创建子进程进程特性优先级进程切换&#xff08;分时操作系统&#xff09; 二.环境变量三.进程地址空间四.进程终止&进程等待五.进程替换六.自定义shell 本篇博客希望简略的介绍进程&#xff…

漫话架构师|什么是系统架构设计师(开篇)

~犬&#x1f4f0;余~ “我欲贱而贵&#xff0c;愚而智&#xff0c;贫而富&#xff0c;可乎&#xff1f; 曰&#xff1a;其唯学乎” 关注犬余&#xff0c;共同进步 技术从此不孤单

在AI智能中有几种重要的神经网络类型?6种重要的神经网络类型分享!

神经网络今天已经变得非常流行&#xff0c;但仍然缺乏对它们的了解。一方面&#xff0c;我们已经看到很多人无法识别各种类型的神经网络及其解决的问题&#xff0c;更不用说区分它们中的每一个了。其次&#xff0c;在某种程度上更糟糕的是&#xff0c;当人们在谈论任何神经网络…

业务幂等性技术架构体系之消息幂等深入剖析

在系统中当使用消息队列时&#xff0c;无论做哪种技术选型&#xff0c;有很多问题是无论如何也不能忽视的&#xff0c;如&#xff1a;消息必达、消息幂等等。本文以典型的RabbitMQ为例&#xff0c;讲解如何保证消息幂等的可实施解决方案&#xff0c;其他MQ选型均可参考。 一、…

【C语言】线程----同步、互斥、条件变量

目录 3. 同步 3.1 概念 3.2 同步机制 3.3 函数接口 1. 同步 1.1 概念 同步(synchronization)指的是多个任务(线程)按照约定的顺序相互配合完成一件事情 1.2 同步机制 通过信号量实现线程间的同步 信号量&#xff1a;通过信号量实现同步操作&#xff1b;由信号量来决定…

Linux内核的启动

一、需求 Linux系统中内核处于硬件和应用层之间。整个系统启动和初始化的过程&#xff0c;Linux内核是在主处理器启动之后才会执行。不同的处理器启动流程并不相同&#xff0c;这就要求内核能支持各种处理器的初始化操作。Liux内核各个模块&#xff0c;大部分设计时做到了体系…

[手机Linux] ubuntu 错误解决

Ubuntu: 1,ttyname failed: Inappropriate ioctl for device 将 /root/.profile 文件中的 mesg n || true 改为如下内容。 vim /root/.profile tty -s && mesg n || true 2,Errors were encountered while processing: XXX XXXX sudo apt-get --purge remove xxx…

Docker的入门

一、安装Docker 本教程参考官网文档&#xff0c;链接如下: CentOS | Docker Docs 这个教程是基于你的虚拟机已经弄好了&#xff08;虚拟机用的CentOS&#xff09;&#xff0c;并且有SecureCRT或者MobaXterm等等任意一个工具 1.1 卸载旧版 如果系统中存在旧版本的Docker&a…

Onedrive精神分裂怎么办(有变更却不同步)

Onedrive有时候会分裂&#xff0c;你在本地删除文件&#xff0c;并没有同步到云端&#xff0c;但是本地却显示同步成功。 比如删掉了一个目录&#xff0c;在本地看已经删掉&#xff0c;onedrive显示已同步&#xff0c;但是别的电脑并不会同步到这个删除操作&#xff0c;在网页版…

机器学习06-正则化

机器学习06-正则化 文章目录 机器学习06-正则化0-核心逻辑脉络1-参考网址3-大模型训练中的正则化1.正则化的定义与作用2.常见的正则化方法及其应用场景2.1 L1正则化&#xff08;Lasso&#xff09;2.2 L2正则化&#xff08;Ridge&#xff09;2.3 弹性网络正则化&#xff08;Elas…

windows 极速安装 Linux (Ubuntu)-- 无需虚拟机

1. 安装 WSL 和 Ubuntu 打开命令行&#xff0c;执行 WSL --install -d ubuntu若报错&#xff0c;则先执行 WSL --update2. 重启电脑 因安装了子系统&#xff0c;需重启电脑才生效 3. 配置 Ubuntu 的账号密码 打开 Ubuntu 的命令行 按提示&#xff0c;输入账号&#xff0c;密…

微信小程序实现个人中心页面

文章目录 1. 官方文档教程2. 编写静态页面3. 关于作者其它项目视频教程介绍 1. 官方文档教程 https://developers.weixin.qq.com/miniprogram/dev/framework/ 2. 编写静态页面 mine.wxml布局文件 <!--index.wxml--> <navigation-bar title"个人中心" ba…

Qt/C++进程间通信:QSharedMemory 使用详解(附演示Demo)

在开发跨进程应用程序时&#xff0c;进程间通信&#xff08;IPC&#xff09;是一个关键问题。Qt 框架提供了多种 IPC 技术&#xff0c;其中 QSharedMemory 是一种高效的共享内存方式&#xff0c;可以实现多个进程之间快速交换数据。本文将详细讲解 QSharedMemory 的概念、用法及…

[UE4图文系列] 5.字符串转中文乱码问题说明

原文连接&#xff1a;[UE4图文系列] 5.字符串转中文乱码问题说明 - 哔哩哔哩 本例以原生C和UE4 C字符串传输中出现的中文乱码问题进行说明 一.乱码示例: 1.直接用中文字符串初始化FString,在蓝图中进行打印 FString GetStrWithChinese() {FString fstr"这是一句中文"…