写真と動画のメディアピッカー

サンプルを参照します。 サンプルを参照する

この記事では、.NET Multi-Platform App UI (.NET MAUI) の IMediaPicker インターフェイスを使用する方法について説明します。 このインターフェイスを使用すると、ユーザーはデバイス上で写真やビデオを選択または撮影できます。

IMediaPicker インターフェイスの既定の実装は、MediaPicker.Default プロパティを通じて利用できます。 IMediaPicker インターフェイスと MediaPicker クラスはどちらも Microsoft.Maui.Media 名前空間に含まれています。

概要

メディア ピッカーの機能にアクセスするには、次のプラットフォーム固有の設定が必要です。

CAMERA 許可が必要であり、Androidプロジェクト内で設定する必要があります。 さらに:

  • アプリが Android 12 以前を対象としている場合は、READ_EXTERNAL_STORAGE および WRITE_EXTERNAL_STORAGE のアクセス許可を要求する必要があります。

  • アプリが Android 13 以降を対象とし、他のアプリが生成したメディアファイルへのアクセスが必要な場合は、READ_EXTERNAL_STORAGE アクセス許可ではなく、次の詳細なメディア アクセス許可を 1 つ以上要求する必要があります。

    • READ_MEDIA_IMAGES
    • READ_MEDIA_VIDEO
    • READ_MEDIA_AUDIO

これらのアクセス許可は、次の方法で追加できます。

  • アセンブリ ベースのアクセス許可を追加します。

    Platforms/Android/MainApplication.cs ファイルを開き、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)]
    

    または

  • Android マニフェストを更新します。

    Platforms/Android/AndroidManifest.xml ファイルを開き、 ノードに次を追加します。

    <!-- 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" />
    

    または

  • マニフェスト エディターで Android マニフェストを更新します。

    Visual Studio で、Platforms/Android/AndroidManifest.xml ファイルをダブルクリックして、Android マニフェスト エディターを開きます。 次に、[必要なアクセス許可] で、上記に一覧表示されたアクセス許可をチェックします。 これにより、AndroidManifest.xml ファイルが自動的に更新されます。

プロジェクトの対象の Android バージョンが Android 11 (R API 30) 以降に設定されている場合は、Android のパッケージの可視性要件を使用するクエリで Android マニフェストを更新する必要があります。

Platforms/Android/AndroidManifest.xml ファイルで、queries/intent ノードに次の manifest ノードを追加します。

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

メディア ピッカーを使用する

IMediaPicker インターフェイスには、ファイルの場所を取得したり読み取ったりするために使用できるFileResultを返す次のメソッドがあります。

  • PickPhotoAsync
    メディア ブラウザーを開いて、写真を選択します。

  • CapturePhotoAsync
    カメラを開いて、写真を撮影します。

  • PickVideoAsync
    メディア ブラウザーを開いて、ビデオを選択します。

  • CaptureVideoAsync
    カメラを開いて、ビデオを撮影します。

各メソッドは、必要に応じて MediaPickerOptions パラメーターを受け取ります。これにより、ユーザーに表示される一部のオペレーティング システムで Title を設定できます。

.NET 10 では、メディア ピッカーによって複数選択のサポートと新しい処理オプションが追加されます。 次のメソッドを使用します。

  • PickPhotosAsync ( List<FileResult>を返します)
    メディア ブラウザーを開き、1 つまたは複数の写真を選択します。

  • CapturePhotoAsync ( FileResult?を返します)
    カメラを開いて、写真を撮影します。

  • PickVideosAsync ( List<FileResult>を返します)
    メディア ブラウザーを開き、1 つ以上のビデオを選択します。

  • CaptureVideoAsync ( FileResult?を返します)
    カメラを開いて、ビデオを撮影します。

MediaPickerOptions パラメーターは、SelectionLimitMaximumWidthMaximumHeightCompressionQualityRotateImagePreserveMetaDataなどの追加のフィールドを公開します。

重要

ユーザーが複数選択操作をキャンセルすると、返されるリストは空になります。 Android では、一部のピッカー UI で SelectionLimitが適用されない場合があります。Windows では、 SelectionLimit はサポートされていません。 制限を適用したり、これらのプラットフォームでユーザーに通知したりするための独自のロジックを実装します。

複数の写真を選ぶ

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
}

複数のビデオを選択する

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
}

ヒント

単一選択の場合は、 PickPhotosAsync/PickVideosAsync も優先します。 SelectionLimit = 1 (既定値) を設定し、最初の項目が存在する場合は読み取る。

重要

アクセス許可のチェックと要求は.NET MAUIによって自動的に処理されるため、カメラまたはピッカー UI を開くメディア ピッカー メソッドは UI スレッドで呼び出す必要があります。

MediaPickerOptions.SaveToGallery プロパティは、キャプチャした写真またはビデオをデバイスのギャラリーにも保存するかどうかを制御します。 既定値は falseであり、プロパティは CapturePhotoAsync 操作と CaptureVideoAsync 操作にのみ適用されます。 メディア選択操作では無視されます。

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

キャプチャしたメディアをギャラリーに保存することは、Android、iOS、Mac Catalyst でサポートされています。 iOS および Mac Catalyst では、 NSPhotoLibraryAddUsageDescription キーが Info.plist に存在する必要があります。 API 29 より前の Android バージョンでは、 WRITE_EXTERNAL_STORAGE アクセス許可が必要です。 プロパティは、Windowsおよび Tizen では無視されます。

中断された Android メディア ピッカー操作を回復する

Android では、カメラまたは写真ピッカー UI が前面にある間、システムはアプリを破棄して再作成できます。 アプリの再開時に元のメディア ピッカー タスクがなくなった場合は、Android 専用の回復 API を使用して、受け入れられた結果を取得します。

AndroidX ベースのメディア ピッカー操作 (写真のキャプチャ、ビデオのキャプチャ、写真の選択、写真の選択、ビデオの選択、ビデオの選択など) で回復できます。 各RecoveredMediaPickerResultには、回復されたId オブジェクトを含むKindFiles、およびFileResult コレクションがあります。 RecoveredMediaPickerResultKind値は、操作をCapturePhotoCaptureVideoPickPhotoPickPhotosPickVideo、またはPickVideosとして識別します。

回復 API は Android 専用であるため、Android 固有のファイルに回復コードを配置するか、共有コード内の #if ANDROID で保護します。

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

MediaPicker.GetRecoveredMediaPickerResultsAsyncを使用して、既に回復した結果に対してクエリを実行し、アプリが各結果を処理した後にMediaPicker.ClearRecoveredMediaPickerResultAsyncを呼び出します。 起動または再開フローで復旧調整を待機する必要がある場合は、MediaPicker.WaitForRecoveredMediaPickerResultsAsyncを使用してCancellationTokenを呼び出します。 アプリで保留中のメディア ピッカー操作を破棄する必要がある場合は、 MediaPicker.DiscardPendingMediaPickerOperationAsyncを呼び出します。

重要

メディア ピッカーの結果の回復は Android 専用であり、iOS、Mac Catalyst、またはWindowsでのメディア ピッカーの動作は変更されません。

写真を撮る

CapturePhotoAsync メソッドを呼び出してカメラを開き、ユーザーが写真を撮れるようにします。 ユーザーが写真を撮影した場合、メソッドの戻り値は null 以外の値になります。 次のコード サンプルでは、メディア ピッカーを使用して写真を撮影し、キャッシュ ディレクトリに保存します。

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);
        }
    }
}

ヒント

The FullPath プロパティは、ファイルへの物理パスを常に返すとは限りません。 ファイルを取得するには、OpenReadAsync メソッドを使用します。