Exibir a visualização da câmera
Este artigo descreve como exibir rapidamente o fluxo de visualização de câmera em uma página XAML de um aplicativo UWP (Plataforma Universal do Windows). Criar um aplicativo que captura fotos e vídeos usando a câmera exige que você realize tarefas como manipular a orientação do dispositivo e da câmera ou definir opções de codificação para o arquivo capturado. Em alguns cenários de aplicativo, talvez você queira simplesmente mostrar o fluxo de visualização da câmera sem se preocupar com essas outras considerações. Este artigo mostra como fazer isso com um mínimo de código. Observe que você deve sempre desligar o fluxo de visualização corretamente quando o tiver concluído, seguindo as etapas abaixo.
Para saber mais sobre como desenvolver um aplicativo de câmera que capture fotos ou vídeos, consulte Captura básica de fotos, vídeo e áudio com o MediaCapture.
Adicionar declarações de funcionalidades ao manifesto do aplicativo
Para que seu app acesse a câmera do dispositivo, você deve declarar que o app usa as funcionalidades de webcam e microphone do dispositivo.
Adicionar funcionalidades ao manifesto do aplicativo
- No Microsoft Visual Studio, no Gerenciador de Soluções, abra o designer do manifesto do aplicativo clicando duas vezes no item package.appxmanifest.
- Selecione a guia Funcionalidades.
- Marque a caixa da Webcam e a caixa do Microfone.
Adicionar um CaptureElement à sua página
Use um CaptureElement para exibir o fluxo de visualização na página XAML.
<CaptureElement Name="PreviewControl" Stretch="Uniform"/>
Usar o MediaCapture para iniciar o fluxo de visualização
O objeto MediaCapture é a interface do seu aplicativo para a câmera do dispositivo. Esta classe é um membro do namespace Windows.Media.Capture. O exemplo deste artigo também usa APIs dos namespaces Windows.ApplicationModel e System.Threading.Tasks, além daqueles incluídos pelo modelo de projeto padrão.
Adicione usando diretivas para incluir os seguintes namespaces no arquivo. cs da sua página.
//MainPage.xaml.cs
using Windows.UI.Core;
using Windows.UI.Xaml.Navigation;
using Windows.Media.Capture;
using Windows.ApplicationModel;
using System.Threading.Tasks;
using Windows.System.Display;
using Windows.Graphics.Display;
Declare uma variável de membro de classe para o objeto MediaCapture e um valor booliano para controlar se a câmera está visualizando no momento.
MediaCapture mediaCapture;
bool isPreviewing;
Declare uma variável do tipo DisplayRequest que será usada para garantir que a exibição não seja desativada enquanto a visualização estiver em execução.
DisplayRequest displayRequest = new DisplayRequest();
Crie um método auxiliar para iniciar a visualização de câmera, chamada StartPreviewAsync neste exemplo. Dependendo do cenário do aplicativo, você pode querer chamá-lo a partir do manipulador de eventos OnNavigatedTo que é chamado quando a página é carregada ou esperar e iniciar a visualização em resposta a eventos da interface do usuário.
Crie uma nova instância da classe MediaCapture e chame InitializeAsync para inicializar o dispositivo de captura. Esse método pode falhar em dispositivos que não têm uma câmera, por exemplo. Por isso, você deve chamá-lo de dentro de um bloco try. Uma UnauthorizedAccessException será lançada quando você tentar inicializar a câmera, se o usuário tiver desabilitado o acesso à câmera nas configurações de privacidade do dispositivo. Você também verá essa exceção durante o desenvolvimento, se não tiver adicionado os recursos adequados ao manifesto do seu aplicativo.
Importante Em algumas famílias de dispositivos, uma solicitação de consentimento do usuário é exibida para o usuário antes de seu aplicativo receber acesso à câmera do dispositivo. Por esse motivo, você só deve chamar MediaCapture.InitializeAsync do thread de interface do usuário principal. Tentar iniciar a câmera de outro thread pode resultar em falha de inicialização.
Observação
O Windows permite que os usuários concedam ou neguem acesso à câmera do dispositivo no aplicativo Configurações do Windows, em Privacidade e Segurança -> Câmera. Ao inicializar o dispositivo de captura, os aplicativos devem verificar se têm acesso à câmera e lidar com o caso em que o acesso é negado pelo usuário. Para mais informações, consulte Manipular a configuração de privacidade da câmera do Windows.
Conecte a MediaCapture ao CaptureElement definindo a propriedade Source. Inicie a visualização chamando StartPreviewAsync. Esse método gerará uma FileLoadException se outro app tiver controle exclusivo do dispositivo de captura. Veja a próxima seção para obter informações sobre as alterações no controle exclusivo.
Chame RequestActive para garantir que o dispositivo não entre em suspensão enquanto a visualização estiver em execução. Por fim, defina a propriedade DisplayInformation.AutoRotationPreferences como Landscape para impedir que a interface do usuário e o CaptureElement girem quando o usuário mudar a orientação do dispositivo. Para obter mais informações sobre como lidar com alterações de orientação do dispositivo, consulte Manipular a orientação do dispositivo com o MediaCapture.
private async Task StartPreviewAsync()
{
try
{
mediaCapture = new MediaCapture();
await mediaCapture.InitializeAsync();
displayRequest.RequestActive();
DisplayInformation.AutoRotationPreferences = DisplayOrientations.Landscape;
}
catch (UnauthorizedAccessException)
{
// This will be thrown if the user denied access to the camera in privacy settings
ShowMessageToUser("The app was denied access to the camera");
return;
}
try
{
PreviewControl.Source = mediaCapture;
await mediaCapture.StartPreviewAsync();
isPreviewing = true;
}
catch (System.IO.FileLoadException)
{
mediaCapture.CaptureDeviceExclusiveControlStatusChanged += _mediaCapture_CaptureDeviceExclusiveControlStatusChanged;
}
}
Manipular as alterações no controle exclusivo
Conforme mencionado na seção anterior, StartPreviewAsync gerará uma FileLoadException se outro aplicativo tiver o controle exclusivo do dispositivo de captura. A partir do Windows 10, versão 1703, você pode registrar um manipulador para o evento MediaCapture.CaptureDeviceExclusiveControlStatusChanged, que é acionado sempre que o status de controle exclusivo do dispositivo é alterado. No manipulador para este evento, verifique a propriedade MediaCaptureDeviceExclusiveControlStatusChangedEventArgs.Status para ver qual é o status atual. Se o novo status for SharedReadOnlyAvailable, então você saberá que no momento não é possível iniciar a visualização e talvez convenha atualizar sua interface do usuário para alertar o usuário. Se o novo status for ExclusiveControlAvailable, então você poderá tentar iniciar a visualização de câmera novamente.
private async void _mediaCapture_CaptureDeviceExclusiveControlStatusChanged(MediaCapture sender, MediaCaptureDeviceExclusiveControlStatusChangedEventArgs args)
{
if (args.Status == MediaCaptureDeviceExclusiveControlStatus.SharedReadOnlyAvailable)
{
ShowMessageToUser("The camera preview can't be displayed because another app has exclusive access");
}
else if (args.Status == MediaCaptureDeviceExclusiveControlStatus.ExclusiveControlAvailable && !isPreviewing)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
await StartPreviewAsync();
});
}
}
Desligar o fluxo de visualização
Ao terminar de usar o fluxo de visualização, você sempre deve desligar o fluxo e dispor corretamente dos recursos associados para garantir que a câmera esteja disponível para outros aplicativos no dispositivo. As etapas necessárias para desligar o fluxo de visualização são:
- Se a câmera estiver atualmente em visualização, chame StopPreviewAsync para interromper o fluxo de visualização. Uma exceção será gerada se você chamar StopPreviewAsync enquanto a visualização não estiver em execução.
- Defina a propriedade Source do CaptureElement como nulo. Use CoreDispatcher.RunAsync para garantir que essa chamada seja executada no thread de interface do usuário.
- Chame o método Dispose do objeto MediaCapture para liberar o objeto. Novamente, use CoreDispatcher.RunAsync para garantir que essa chamada seja executada no thread de interface do usuário.
- Defina a variável do membro do MediaCapture como nulo.
- Chame RequestRelease para permitir que a tela seja desativada quando inativa.
private async Task CleanupCameraAsync()
{
if (mediaCapture != null)
{
if (isPreviewing)
{
await mediaCapture.StopPreviewAsync();
}
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
PreviewControl.Source = null;
if (displayRequest != null)
{
displayRequest.RequestRelease();
}
mediaCapture.Dispose();
mediaCapture = null;
});
}
}
Você deve desligar o fluxo de visualização quando o usuário navegar para fora de sua página, substituindo o método OnNavigatedFrom.
protected async override void OnNavigatedFrom(NavigationEventArgs e)
{
await CleanupCameraAsync();
}
Você também deve desligar o fluxo de visualização corretamente quando seu aplicativo estiver suspenso. Para fazer isso, registre um manipulador para o evento Application.Suspending no construtor da página.
public MainPage()
{
this.InitializeComponent();
Application.Current.Suspending += Application_Suspending;
}
No manipulador de eventos Suspending, verifique primeiro se a página está exibindo o Frame do aplicativo, comparando o tipo de página com a propriedade CurrentSourcePageType. Se a página não estiver sendo exibida no momento, o evento OnNavigatedFrom já deve tiver sido gerado e o fluxo de visualização encerrado. Se a página estiver sendo exibida no momento, obtenha um objeto SuspendingDeferral dos argumentos de evento passados para o manipulador para garantir que o sistema não suspenda seu aplicativo até que o fluxo de visualização seja encerrado. Depois de desligar o fluxo, chame o método Complete de adiamento para permitir que o sistema continue a suspender seu aplicativo.
private async void Application_Suspending(object sender, SuspendingEventArgs e)
{
// Handle global application events only if this page is active
if (Frame.CurrentSourcePageType == typeof(MainPage))
{
var deferral = e.SuspendingOperation.GetDeferral();
await CleanupCameraAsync();
deferral.Complete();
}
}