Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Importante
Este recurso dos Serviços de Comunicação do Azure estão atualmente em versão prévia. Os recursos em versão prévia estão disponíveis publicamente e podem ser usados por todos os clientes novos e existentes da Microsoft.
Versões prévias das APIs e dos SDKs são fornecidas sem um contrato de nível de serviço. É recomendável que você não as use para cargas de trabalho de produção. Alguns recursos podem não ter suporte ou recursos podem ser restritos.
Para obter mais informações, consulte Termos de Uso Complementares de Versões Prévias do Microsoft Azure.
Este tutorial é uma continuação de uma série de três partes de tutoriais de Preparação de Chamadas e segue do anterior: Verifique se o usuário está em um navegador com suporte.
Código de download
Acesse o código completo deste tutorial sobre GitHub.
Solicitando acesso à câmera e ao microfone
Para chamar aplicativos, geralmente é vital que um usuário tenha dado permissão para usar o microfone e a câmera. Nesta seção, criamos uma série de componentes que incentivam o usuário a conceder acesso à câmera e ao microfone. Exibimos solicitações ao usuário para guiá-los por meio da concessão de acesso. Informamos ao usuário com um prompt se o acesso não for concedido.
Como criar avisos para acesso à câmera e ao microfone
Primeiro, criamos uma série de solicitações de permissões de dispositivo para colocar os usuários em um estado em que eles aceitaram as permissões de microfone e câmera. Esses avisos usam o componente CameraAndMicrophoneSitePermissions
da Biblioteca de IU. Como o aviso Navegador sem suporte, hospedamos esses avisos em um modal
do FluentUI.
src/DevicePermissionPrompts.tsx
import { CameraAndMicrophoneSitePermissions } from '@azure/communication-react';
import { Modal } from '@fluentui/react';
/** Modal dialog that prompt the user to accept the Browser's device permission request. */
export const AcceptDevicePermissionRequestPrompt = (props: { isOpen: boolean }): JSX.Element => (
<PermissionsModal isOpen={props.isOpen} kind="request" />
);
/** Modal dialog that informs the user we are checking for device access. */
export const CheckingDeviceAccessPrompt = (props: { isOpen: boolean }): JSX.Element => (
<PermissionsModal isOpen={props.isOpen} kind="check" />
)
/** Modal dialog that informs the user they denied permission to the camera or microphone with corrective steps. */
export const PermissionsDeniedPrompt = (props: { isOpen: boolean }): JSX.Element => (
<PermissionsModal isOpen={props.isOpen} kind="denied" />
);
/** Base component utilized by the above prompts for better code separation. */
const PermissionsModal = (props: { isOpen: boolean, kind: "denied" | "request" | "check" }): JSX.Element => (
<Modal isOpen={props.isOpen}>
<CameraAndMicrophoneSitePermissions
appName={'this site'}
kind={props.kind}
onTroubleshootingClick={() => alert('This callback should be used to take the user to further troubleshooting')}
/>
</Modal>
);
Verificando se há acesso à câmera e ao microfone
Aqui, adicionamos duas novas funções de utilitário para verificar e solicitar acesso à câmera e ao microfone. Crie um arquivo chamado devicePermissionUtils.ts
com duas funções checkDevicePermissionsState
e requestCameraAndMicrophonePermissions
.
checkDevicePermissionsState
usa o PermissionAPI. No entanto, não há suporte para a consulta de câmera e microfone no Firefox e, portanto, garantimos que esse método retorne unknown
nesse caso. Posteriormente, garantimos que lidamos com o unknown
caso ao solicitar permissões ao usuário.
src/DevicePermissionUtils.ts
import { DeviceAccess } from "@azure/communication-calling";
import { StatefulCallClient } from "@azure/communication-react";
/**
* Check if the user needs to be prompted for camera and microphone permissions.
*
* @remarks
* The Permissions API we are using is not supported in Firefox, Android WebView or Safari < 16.
* In those cases this returns 'unknown'.
*/
export const checkDevicePermissionsState = async (): Promise<{camera: PermissionState, microphone: PermissionState} | 'unknown'> => {
try {
const [micPermissions, cameraPermissions] = await Promise.all([
navigator.permissions.query({ name: "microphone" as PermissionName }),
navigator.permissions.query({ name: "camera" as PermissionName })
]);
console.info('PermissionAPI results', [micPermissions, cameraPermissions]); // view console logs in the browser to see what the PermissionsAPI info is returned
return { camera: cameraPermissions.state, microphone: micPermissions.state };
} catch (e) {
console.warn("Permissions API unsupported", e);
return 'unknown';
}
}
/** Use the DeviceManager to request for permissions to access the camera and microphone. */
export const requestCameraAndMicrophonePermissions = async (callClient: StatefulCallClient): Promise<DeviceAccess> => {
const response = await (await callClient.getDeviceManager()).askDevicePermission({ audio: true, video: true });
console.info('AskDevicePermission response', response); // view console logs in the browser to see what device access info is returned
return response
}
Solicitando que o usuário conceda acesso à câmera e ao microfone
Agora que temos os prompts e a lógica de verificação e solicitação, criamos um DeviceAccessComponent
para solicitar ao usuário as permissões do dispositivo.
Neste componente, exibimos prompts diferentes para o usuário com base no estado de permissão do dispositivo:
- Se o estado de permissão do dispositivo for desconhecido, exibiremos um prompt para o usuário informando que estamos verificando se há permissões de dispositivo.
- Se estivermos solicitando permissões, exibiremos uma solicitação ao usuário incentivando-o a aceitar a solicitação de permissões.
- Se as permissões forem negadas, exibiremos uma solicitação ao usuário informando que ele negou permissões e que precisa conceder permissões para continuar.
src/DeviceAccessChecksComponent.tsx
import { useEffect, useState } from 'react';
import { CheckingDeviceAccessPrompt, PermissionsDeniedPrompt, AcceptDevicePermissionRequestPrompt } from './DevicePermissionPrompts';
import { useCallClient } from '@azure/communication-react';
import { checkDevicePermissionsState, requestCameraAndMicrophonePermissions } from './DevicePermissionUtils';
export type DevicesAccessChecksState = 'runningDeviceAccessChecks' |
'checkingDeviceAccess' |
'promptingForDeviceAccess' |
'deniedDeviceAccess';
/**
* This component is a demo of how to use the StatefulCallClient with CallReadiness Components to get a user
* ready to join a call.
* This component checks the browser support and if camera and microphone permissions have been granted.
*/
export const DeviceAccessChecksComponent = (props: {
/**
* Callback triggered when the tests are complete and successful
*/
onTestsSuccessful: () => void
}): JSX.Element => {
const [currentCheckState, setCurrentCheckState] = useState<DevicesAccessChecksState>('runningDeviceAccessChecks');
// Run call readiness checks when component mounts
const callClient = useCallClient();
useEffect(() => {
const runDeviceAccessChecks = async (): Promise<void> => {
// First we check if we need to prompt the user for camera and microphone permissions.
// The prompt check only works if the browser supports the PermissionAPI for querying camera and microphone.
// In the event that is not supported, we show a more generic prompt to the user.
const devicePermissionState = await checkDevicePermissionsState();
if (devicePermissionState === 'unknown') {
// We don't know if we need to request camera and microphone permissions, so we'll show a generic prompt.
setCurrentCheckState('checkingDeviceAccess');
} else if (devicePermissionState.camera === 'prompt' || devicePermissionState.microphone === 'prompt') {
// We know we need to request camera and microphone permissions, so we'll show the prompt.
setCurrentCheckState('promptingForDeviceAccess');
}
// Now the user has an appropriate prompt, we can request camera and microphone permissions.
const devicePermissionsState = await requestCameraAndMicrophonePermissions(callClient);
if (!devicePermissionsState.audio || !devicePermissionsState.video) {
// If the user denied camera and microphone permissions, we prompt the user to take corrective action.
setCurrentCheckState('deniedDeviceAccess');
} else {
// Test finished successfully, trigger callback to parent component to take user to the next stage of the app.
props.onTestsSuccessful();
}
};
runDeviceAccessChecks();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<>
{/* We show this when we are prompting the user to accept device permissions */}
<AcceptDevicePermissionRequestPrompt isOpen={currentCheckState === 'promptingForDeviceAccess'} />
{/* We show this when the PermissionsAPI is not supported and we are checking what permissions the user has granted or denied */}
<CheckingDeviceAccessPrompt isOpen={currentCheckState === 'checkingDeviceAccess'} />
{/* We show this when the user has failed to grant camera and microphone access */}
<PermissionsDeniedPrompt isOpen={currentCheckState === 'deniedDeviceAccess'} />
</>
);
}
Depois que terminarmos de criar esse componente, o adicionaremos ao App.tsx
. Primeiro, adicione a importação:
import { DeviceAccessChecksComponent } from './DeviceAccessChecksComponent';
Em seguida, atualize o TestingState
tipo para ser o seguinte valor:
type TestingState = 'runningEnvironmentChecks' | 'runningDeviceAccessChecks' | 'finished';
Por fim, atualize o App
componente:
/**
* Entry point of a React app.
*
* This shows a PreparingYourSession component while the CallReadinessChecks are running.
* Once the CallReadinessChecks are finished, the TestComplete component is shown.
*/
const App = (): JSX.Element => {
const [testState, setTestState] = useState<TestingState>('runningEnvironmentChecks');
return (
<FluentThemeProvider>
<CallClientProvider callClient={callClient}>
{/* Show a Preparing your session screen while running the environment checks */}
{testState === 'runningEnvironmentChecks' && (
<>
<PreparingYourSession />
<EnvironmentChecksComponent onTestsSuccessful={() => setTestState('runningDeviceAccessChecks')} />
</>
)}
{/* Show a Preparing your session screen while running the device access checks */}
{testState === 'runningDeviceAccessChecks' && (
<>
<PreparingYourSession />
<DeviceAccessChecksComponent onTestsSuccessful={() => setTestState('finished')} />
</>
)}
{/* After the device setup is complete, take the user to the call. For this sample we show a test complete page. */}
{testState === 'finished' && <TestComplete />}
</CallClientProvider>
</FluentThemeProvider>
);
}
O aplicativo apresenta ao usuário avisos para guiá-lo por meio do acesso ao dispositivo.
Observação
Para testar, recomendamos visitar seu aplicativo no modo InPrivate/Incógnito para que as permissões de câmera e microfone não tenham sido concedidas anteriormente.localhost:3000