Seletor de mídia para fotos e vídeos

Procurar amostra. Procurar no exemplo

Este artigo descreve como você pode usar a interface do usuário do aplicativo .NET multiplataforma (.NET MAUI) IMediaPicker. Essa interface permite que um usuário escolha ou tire uma foto ou faça vídeo no dispositivo.

A implementação padrão da interface IMediaPicker está disponível por meio da propriedade MediaPicker.Default. A interface IMediaPicker e a classe MediaPicker estão contidas no namespace Microsoft.Maui.Media.

Introdução

Para acessar a funcionalidade seletor de mídia, a configuração específica da plataforma a seguir é necessária.

A permissão CAMERA é necessária e deve ser configurada no projeto Android. Além disso:

  • Se o seu aplicativo for direcionado para o Android 12 ou versões anteriores, você deve solicitar as permissões READ_EXTERNAL_STORAGE e WRITE_EXTERNAL_STORAGE.

  • Se seu app for direcionado ao Android 13 ou versões mais recentes e precisar de acesso a arquivos de mídia criados por outros apps, solicite uma ou mais das seguintes permissões de mídia específicas em substituição à permissão READ_EXTERNAL_STORAGE:

    • READ_MEDIA_IMAGES
    • READ_MEDIA_VIDEO
    • READ_MEDIA_AUDIO

Essas permissões podem ser adicionadas das seguintes maneiras:

  • Adicione as permissões baseadas em assembly:

    Abra o arquivo Platforms/Android/MainApplication.cs e adicione os seguintes atributos de assembly após as diretivas using:

    // Needed for Picking photo/video
    [assembly: UsesPermission(Android.Manifest.Permission.ReadExternalStorage, MaxSdkVersion = 32)]
    [assembly: UsesPermission(Android.Manifest.Permission.ReadMediaAudio)]
    [assembly: UsesPermission(Android.Manifest.Permission.ReadMediaImages)]
    [assembly: UsesPermission(Android.Manifest.Permission.ReadMediaVideo)]
    
    // Needed for Taking photo/video
    [assembly: UsesPermission(Android.Manifest.Permission.Camera)]
    [assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage, MaxSdkVersion = 32)]
    
    // Add these properties if you would like to filter out devices that do not have cameras, or set to false to make them optional
    [assembly: UsesFeature("android.hardware.camera", Required = true)]
    [assembly: UsesFeature("android.hardware.camera.autofocus", Required = true)]
    

    - ou -

  • Atualize o manifesto do Android:

    Abra o arquivo Platforms/Android/AndroidManifest.xml e adicione o seguinte no nó manifest:

    <!-- Needed for Picking photo/video -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
    
    <!-- Needed for Taking photo/video -->
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
    
    <!-- Add these properties if you would like to filter out devices that do not have cameras, or set to false to make them optional -->
    <uses-feature android:name="android.hardware.camera" android:required="true" />
    <uses-feature android:name="android.hardware.camera.autofocus" android:required="true" />
    

    - ou -

  • Atualize o Manifesto do Android no editor de manifesto:

    No Visual Studio, clique duas vezes no arquivo Platforms/Android/AndroidManifest.xml para abrir o editor de manifesto do Android. Em seguida, em Permissões necessárias, verifique as permissões listadas acima. Isso atualizará automaticamente o arquivo AndroidManifest.xml.

Se a versão Target Android do seu projeto estiver definida como Android 11 (R API 30) ou superior, você deverá atualizar seu Android Manifest com consultas que atendam aos requisitos de visibilidade de pacotes do Android.

No arquivo Platforms/Android/AndroidManifest.xml, adicione os seguintes nós queries/intent no nó manifest:

<queries>
  <intent>
    <action android:name="android.media.action.IMAGE_CAPTURE" />
  </intent>
</queries>

Uso do seletor de mídia

A IMediaPicker interface tem os métodos a seguir que retornam um FileResult, que pode ser usado para obter o local do arquivo ou lê-lo.

Cada método opcionalmente toma um parâmetro MediaPickerOptions que permite definir o Title em alguns sistemas operacionais, o qual é exibido para o usuário.

No .NET 10, o seletor de mídia adiciona suporte de várias seleções e novas opções de processamento. Use os seguintes métodos:

  • PickPhotosAsync (retorna List<FileResult>)
    Abre o navegador de mídia para selecionar uma ou mais fotos.

  • CapturePhotoAsync (retorna FileResult?)
    Abre a câmera para tirar uma foto.

  • PickVideosAsync (retorna List<FileResult>)
    Abre o navegador de mídia para selecionar um ou mais vídeos.

  • CaptureVideoAsync (retorna FileResult?)
    Abre a câmera para gravar um vídeo.

O MediaPickerOptions parâmetro expõe campos adicionais, como SelectionLimit, MaximumWidth, MaximumHeight, , CompressionQualitye RotateImagePreserveMetaData.

Importante

Quando o usuário cancela uma operação de seleção múltipla, a lista retornada fica vazia. No Android, algumas interfaces de usuário do seletor podem não aplicar SelectionLimit; no Windows, SelectionLimit não é suportado. Implemente sua própria lógica para impor limites ou notificar o usuário nessas plataformas.

Escolher várias fotos

var results = await MediaPicker.PickPhotosAsync(new MediaPickerOptions
{
  // Default is 1; set to 0 for no limit
  SelectionLimit = 10,
  // Optional processing for images
  MaximumWidth = 1024,
  MaximumHeight = 768,
  CompressionQuality = 85,
  RotateImage = true,
  PreserveMetaData = true,
});

foreach (var file in results)
{
  using var stream = await file.OpenReadAsync();
  // Process the stream
}

Escolher vários vídeos

var results = await MediaPicker.PickVideosAsync(new MediaPickerOptions
{
  SelectionLimit = 3,
  Title = "Select up to 3 videos",
});

foreach (var file in results)
{
  using var stream = await file.OpenReadAsync();
  // Process the stream
}

Dica

Para seleção única, prefira PickPhotosAsync/PickVideosAsync também. Defina SelectionLimit = 1 (o padrão) e leia o primeiro item, se presente.

Importante

Os métodos de seletor de mídia que abrem a interface do usuário da câmera ou do seletor devem ser chamados no thread da interface do usuário porque as verificações de permissão e as solicitações são tratadas automaticamente por .NET MAUI.

A MediaPickerOptions.SaveToGallery propriedade controla se uma foto ou vídeo capturado também é salvo na galeria do dispositivo. O valor padrão é false, e a propriedade só se aplica a operações e operações CapturePhotoAsyncCaptureVideoAsync . Ela é ignorada por operações de seleção de mídia.

FileResult? photo = await MediaPicker.Default.CapturePhotoAsync(
    new MediaPickerOptions
    {
        SaveToGallery = true
    });

Há suporte para salvar mídia capturada na galeria no Android, iOS e Mac Catalyst. No iOS e no Mac Catalyst, a NSPhotoLibraryAddUsageDescription chave deve estar presente no Info.plist. Em versões do Android anteriores à API 29, a WRITE_EXTERNAL_STORAGE permissão é necessária. A propriedade é ignorada em Windows e Tizen.

Recuperar operações interrompidas do seletor de mídia no Android

No Android, o sistema pode destruir e recriar seu aplicativo enquanto a interface da câmera ou do seletor de fotos estiver em primeiro plano. Se a tarefa original do seletor de mídia não estiver mais disponível quando seu aplicativo for retomado, use as APIs de recuperação exclusivas do Android para recuperar os resultados já aceitos.

A recuperação está disponível para operações de seletor de mídia apoiadas pelo AndroidX: capturar foto, capturar vídeo, escolher uma foto, escolher fotos, escolher um vídeo e escolher vídeos. Cada RecoveredMediaPickerResult tem um Id, um Kind e uma coleção Files que contém objetos FileResult recuperados. O RecoveredMediaPickerResultKind valor identifica a operação como CapturePhoto, , CaptureVideo, PickPhoto, PickPhotos, PickVideoou PickVideos.

Como as APIs de recuperação são exclusivas do Android, coloque o código de recuperação em um arquivo específico para Android ou proteja-o com #if ANDROID no código compartilhado.

using System.IO;
using Microsoft.Maui.Media;
using Microsoft.Maui.Storage;

#if ANDROID
async Task RecoverMediaPickerResultsAsync()
{
    var results = await MediaPicker.GetRecoveredMediaPickerResultsAsync();

    foreach (var result in results)
    {
        foreach (var file in result.Files)
        {
            var destination = Path.Combine(FileSystem.CacheDirectory, file.FileName);

            using var source = await file.OpenReadAsync();
            using var target = File.Create(destination);
            await source.CopyToAsync(target);
        }

        await MediaPicker.ClearRecoveredMediaPickerResultAsync(result.Id);
    }
}
#endif

Use MediaPicker.GetRecoveredMediaPickerResultsAsync para consultar os resultados já recuperados e chame MediaPicker.ClearRecoveredMediaPickerResultAsync depois que seu aplicativo processar cada resultado. Se o fluxo de inicialização ou o fluxo de retomada precisar aguardar a conclusão da reconciliação de recuperação, chame MediaPicker.WaitForRecoveredMediaPickerResultsAsync com um CancellationToken. Se o aplicativo precisar abandonar uma operação pendente do seletor de mídia, chame MediaPicker.DiscardPendingMediaPickerOperationAsync.

Importante

A recuperação de resultados do seletor de mídia é somente Android e não altera o comportamento do seletor de mídia no iOS, Mac Catalyst ou Windows.

Tirar uma foto

Chame o método CapturePhotoAsync para abrir a câmera e permitir ao usuário tirar uma foto. Se o usuário tirar uma foto, o valor retornado do método será um valor não nulo. O exemplo de código a seguir usa o seletor de mídia para tirar uma foto e salvá-la no diretório de cache:

public async void TakePhoto()
{
    if (MediaPicker.Default.IsCaptureSupported)
    {
        FileResult photo = await MediaPicker.Default.CapturePhotoAsync();

        if (photo != null)
        {
            // save the file into local storage
            string localFilePath = Path.Combine(FileSystem.CacheDirectory, photo.FileName);

            using Stream sourceStream = await photo.OpenReadAsync();
            using FileStream localFileStream = File.OpenWrite(localFilePath);

            await sourceStream.CopyToAsync(localFileStream);
        }
    }
}

Dica

A propriedade FullPath nem sempre retorna o caminho físico para o arquivo. Para obter o arquivo, use o método OpenReadAsync.