query
一、认识
permissions.query()
用于查询浏览器中某个特定权限的状态。开发者可以通过这个方法来了解用户是否授予了特定的权限,例如相机、麦克风、地理位置等,从而决定是否启用某些功能或者显示相应的用户提示。这个方法返回一个 Promise
,该 Promise
解析为一个 PermissionsStatus
对象,该对象包含了权限的状态信息。这使得开发者能够根据用户的权限设置采取相应的行动,而不是在没有必要时打扰用户。
二、语法
navigator.permissions.query({name: 'permission-name'}).then(function(permissionStatus) {
// 处理权限状态
if (permissionStatus.state === 'granted') {
// 权限被授予
} else if (permissionStatus.state === 'denied') {
// 权限被拒绝
} else {
// 权限提示:用户还未被询问是否授予权限
}
});
三、权限
3.1 Chrome
enum PermissionName {
"geolocation",
"notifications",
"push",
"midi",
"camera",
"microphone",
// "speaker",
// "device-info",
"background-fetch",
"background-sync",
// "bluetooth",
"persistent-storage",
"ambient-light-sensor",
"accelerometer",
"gyroscope",
"magnetometer",
// "clipboard",
"screen-wake-lock",
"nfc",
"display-capture",
// Non-standard:
"accessibility-events",
"clipboard-read",
"clipboard-write",
"payment-handler",
"idle-detection",
"periodic-background-sync",
"system-wake-lock",
"storage-access",
"window-management",
// Alias for 'window-management' (crbug.com/1328581).
"window-placement",
"local-fonts",
"top-level-storage-access",
"captured-surface-control",
};
3.2 Firefox
enum PermissionName {
"geolocation",
"notifications",
"push",
"persistent-storage",
"midi",
"storage-access", // Defined in https://privacycg.github.io/storage-access/#permissions-integration
"screen-wake-lock" // Defined in https://w3c.github.io/screen-wake-lock/
};
3.3 Safari
enum PermissionName {
// FIXME: update the list to match spec when new features are implemented.
"accelerometer",
"background-fetch",
"bluetooth",
"camera",
"display-capture",
"geolocation",
"gyroscope",
"magnetometer",
"microphone",
"midi",
"nfc",
"notifications",
"push",
"screen-wake-lock",
"speaker-selection"
};
四、场景
4.1 查询权限
async function checkPermissions(name) {
try {
return await navigator.permissions.query({ name: name });
} catch (error) {
return false;
}
}
4.2 视频录制
描述: 在实现视频录制功能时,检查 navigator.permissions.query({ name: 'camera' })
摄像头权限 和 navigator.permissions.query({ name: 'microphone' })
麦克风权限是非常重要的步骤。这里有几个原因:
-
用户隐私和安全:
Web
应用请求访问用户的摄像头和麦克风涉及到用户的隐私和安全。用户有权了解哪个应用程序正在请求这些权限,并有权在允许或拒绝这些权限前做出明智的决策。通过检查权限,开发者可以确保尊重用户对其隐私和安全的控制。 -
Web
标准和浏览器兼容性: 现代Web
浏览器遵循特定的标准来管理权限请求。navigator.permissions.query
方法符合这些标准,并可以帮助开发者了解某个权限的当前状态(如granted
、denied
或prompt
),因此能更好地处理多种情况和浏览器差异。 -
用户体验(
UX
): 正确处理权限请求可以提升用户体验。当应用在不适当的时刻(如一打开网页)立即请求访问摄像头和麦克风时,这可能让用户感到困扰并可能导致用户拒绝。相反,当用户明白自己为何要提供这些权限时,他们更可能授予权限。 -
错误处理: 在请求使用这些设备之前去检查权限状态可以帮助应用提前发现可能的问题,并且提供给用户清晰的反馈或引导用户如何授予权限。如果用户已经拒绝了权限,应用可能会给出指导,说明如何在浏览器的设置中改变这些权限。
-
遵守政策和法规: 某些国家/地区有严格的法律和规定来保护用户隐私,其中可能就包括如何请求和使用设备的摄像头和麦克风。通过适当检查和请求权限,开发者可以确保应用遵守这些法律和规定。
因此,在实现视频录制功能中,正确地处理摄像头和麦克风权限,不仅是出于技术的需要,更是对用户隐私和体验的尊重。最好的实践是在用户明确进行了可能需要这些设备的操作(比如点击了一个“开始视频录制”按钮)后,再请求这些权限。这样,用户会明白为什么他们的权限被请求,并且更有可能授予所需的权限。
<div class="operation">
<button id="start-record">录制</button>
<button id="stop-record">停止</button>
</div>
<div class="video-container">
<video id="video" autoplay></video>
</div>
<script>
let mediaRecorder = null;
const recordedBlobs = [];
const video = document.getElementById('video');
const startRecordEl = document.getElementById('start-record');
const stopRecordEl = document.getElementById('stop-record');
function startRecord() {
const timeSlice = 5000;
mediaRecorder.start(timeSlice);
}
async function stopRecord() {
const stream = video.srcObject;
const tracks = stream.getTracks();
tracks.forEach(track => {
track.stop();
});
video.srcObject = null;
mediaRecorder.stop();
}
async function prepareRecord() {
const stream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true
});
video.srcObject = stream;
video.play();
mediaRecorder = new MediaRecorder(stream, {
mimeType: 'video/webm'
});
mediaRecorder.ondataavailable = event => {
if (event.data && event.data.size > 0) {
recordedBlobs.push(event.data);
}
};
}
async function checkPermissions(name) {
try {
return await navigator.permissions.query({ name: name });
} catch (error) {
return false;
}
}
async function run() {
const camera = await checkPermissions('camera'); // 检测相机权限
const microphone = await checkPermissions('microphone'); // 检测麦克风权限
if (camera.state === 'granted' && microphone.state === 'granted') {
prepareRecord();
startRecordEl.addEventListener('click', startRecord);
stopRecordEl.addEventListener('click', stopRecord);
} else {
alert('请允许使用摄像头和麦克风');
}
}
run();
</script>