次の方法で共有


ミュージック、画像、ビデオ ライブラリ内のファイルとフォルダー

音楽、画像、またはビデオの既存のフォルダーを対応するライブラリに追加します。 ライブラリからフォルダーを削除したり、ライブラリ内のフォルダーの一覧を取得したり、保存されている写真、音楽、ビデオを検出したりすることもできます。

ライブラリは、既定で既知のフォルダーと、ユーザーがアプリまたは組み込みのアプリのいずれかを使用してライブラリに追加した他のフォルダーを含む、フォルダーの仮想コレクションです。 たとえば、Pictures ライブラリには、既定で画像の既知のフォルダーが含まれています。 ユーザーは、アプリまたは組み込みのフォト アプリを使用して、画像ライブラリにフォルダーを追加または削除できます。

[前提条件]

  • ユニバーサル Windows プラットフォーム (UWP) アプリの非同期プログラミングについて

    C# または Visual Basic で非同期アプリを記述する方法については、「C# または Visual Basicでの非同期 API の呼び出し に関するページを参照してください。 C++ で非同期アプリを記述する方法については、「C++での非同期プログラミング」を参照してください。

  • 場所へのアクセス許可

    Visual Studio で、マニフェスト デザイナーでアプリ マニフェスト ファイルを開きます。 [機能] ページで、アプリが管理するライブラリを選択します。

    • ミュージックライブラリ
    • 画像ライブラリ
    • ビデオ ライブラリ

    詳細については、「ファイル アクセス許可の」を参照してください。

ライブラリへの参照を取得する

適切な機能を宣言することを忘れないでください。 詳細については、「アプリ機能宣言」を参照してください。  

ユーザーの Music、Pictures、または Video ライブラリへの参照を取得するには、StorageLibrary.GetLibraryAsync メソッドを呼び出します。 KnownLibraryId 列挙体から対応する値を指定します。

var myPictures = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Pictures);

ライブラリ内のフォルダーの一覧を取得する

ライブラリ内のフォルダーの一覧を取得するには、StorageLibrary.Folders プロパティの値を取得します。

using Windows.Foundation.Collections;
IObservableVector<Windows.Storage.StorageFolder> myPictureFolders = myPictures.Folders;

新しいファイルが既定で保存されているライブラリ内のフォルダーを取得する

新しいファイルが既定で保存されているライブラリ内のフォルダーを取得するには、StorageLibrary.SaveFolder プロパティの値を取得します。

Windows.Storage.StorageFolder savePicturesFolder = myPictures.SaveFolder;

ライブラリに既存のフォルダーを追加する

ライブラリにフォルダーを追加するには、StorageLibrary.RequestAddFolderAsyncを呼び出します。 画像ライブラリを例として使用すると、このメソッドを呼び出すと、フォルダー ピッカーが [画像に追加] ボタンを使用してユーザーに表示されます。 ユーザーがフォルダーを選択した場合、フォルダーはディスク上の元の場所に残り、StorageLibrary.Folders プロパティ (および組み込みのフォト アプリ内) のアイテムになりますが、フォルダーはエクスプローラーの Pictures フォルダーの子として表示されません。

Windows.Storage.StorageFolder newFolder = await myPictures.RequestAddFolderAsync();

ライブラリからフォルダーを削除する

ライブラリからフォルダーを削除するには、StorageLibrary.RequestRemoveFolderAsync メソッドを呼び出し、削除するフォルダーを指定します。 ユーザーが削除するフォルダーを選択するには、StorageLibrary.FoldersListView コントロール (または同様) を使用できます。

StorageLibrary.RequestRemoveFolderAsync呼び出すと、フォルダーが "画像には表示されなくなりますが、削除されません" という確認ダイアログが表示されます。つまり、フォルダーはディスク上の元の場所に残り、StorageLibrary.Folders プロパティから削除され、組み込みのフォト アプリには含まれません。

次の例では、ユーザーが lvPictureFoldersという名前の ListView コントロールから削除するフォルダー 選択していることを前提としています。

bool result = await myPictures.RequestRemoveFolderAsync(folder);

ライブラリ内のフォルダーの一覧に対する変更の通知を受け取る

ライブラリ内のフォルダーの一覧に対する変更に関する通知を受け取るには、ライブラリの StorageLibrary.DefinitionChanged イベントのハンドラーを登録します。

myPictures.DefinitionChanged += MyPictures_DefinitionChanged;

void HandleDefinitionChanged(Windows.Storage.StorageLibrary sender, object args)
{
    // ...
}

メディア ライブラリ フォルダー

デバイスには、ユーザーとアプリがメディア ファイルを格納するための定義済みの場所が 5 つ用意されています。 組み込みのアプリは、ユーザーが作成したメディアとダウンロードしたメディアの両方をこれらの場所に格納します。

場所は次のとおりです。

  • 画像 フォルダー。 画像が含まれています。

    • カメラ ロール フォルダー 組み込みのカメラからの写真とビデオが含まれています。

    • 保存した画像フォルダー です。 ユーザーが他のアプリから保存した画像が含まれています。

  • ミュージック フォルダー 曲、ポッドキャスト、オーディオ ブックが含まれています。

  • ビデオ フォルダー。 ビデオが含まれています。

ユーザーまたはアプリは、SD カードのメディア ライブラリ フォルダーの外部にメディア ファイルを格納することもできます。 SD カードでメディア ファイルを確実に見つけるには、SD カードの内容をスキャンするか、ファイル ピッカーを使用してファイルを検索するようにユーザーに依頼します。 詳細については、「SD カードにアクセスする」を参照してください。

メディア ライブラリのクエリ

ファイルのコレクションを取得するには、ライブラリと必要なファイルの種類を指定します。

using Windows.Storage;
using Windows.Storage.Search;

private async void getSongs()
{
    QueryOptions queryOption = new QueryOptions
        (CommonFileQuery.OrderByTitle, new string[] { ".mp3", ".mp4", ".wma" });

    queryOption.FolderDepth = FolderDepth.Deep;

    Queue<IStorageFolder> folders = new Queue<IStorageFolder>();

    var files = await KnownFolders.MusicLibrary.CreateFileQueryWithOptions
      (queryOption).GetFilesAsync();

    foreach (var file in files)
    {
        // do something with the music files
    }
}

クエリ結果には、内部ストレージとリムーバブル ストレージの両方が含まれます

ユーザーは、オプションの SD カードに既定でファイルを保存することを選択できます。 ただし、アプリでは、SD カードにファイルを保存することをオプトアウトできます。 その結果、メディア ライブラリをデバイスの内部ストレージと SD カードに分割できます。

この可能性を処理するために追加のコードを記述する必要はありません。 既知のフォルダーに対してクエリを実行する Windows.Storage 名前空間内のメソッドは、両方の場所からのクエリ結果を透過的に結合します。 これらの結合された結果を取得するために、アプリ マニフェスト ファイルで removableStorage 機能を指定する必要もありません。

次の図に示すデバイスのストレージの状態を考えてみましょう。

携帯電話とSDカードにある画像

await KnownFolders.PicturesLibrary.GetFilesAsync()を呼び出して画像ライブラリの内容を照会すると、結果には internalPic.jpg と SDPic.jpgの両方が含まれます。

写真の操作

カメラが低解像度の画像とすべての画像の高解像度画像の両方を保存するデバイスでは、ディープ クエリは低解像度の画像のみを返します。

カメラ ロールと保存された画像フォルダーは、詳細クエリをサポートしていません。

キャプチャしたアプリで写真を開く

後でキャプチャしたアプリでユーザーに写真をもう一度開かせたい場合は、次の例のようなコードを使用して、CreatorAppId を写真のメタデータと共に保存できます。 この例では、testPhotoStorageFileです。

IDictionary<string, object> propertiesToSave = new Dictionary<string, object>();

propertiesToSave.Add("System.CreatorOpenWithUIOptions", 1);
propertiesToSave.Add("System.CreatorAppId", appId);

testPhoto.Properties.SavePropertiesAsync(propertiesToSave).AsyncWait();   

ストリーム メソッドを使用してメディア ライブラリにファイルを追加する

KnownFolders.PictureLibraryなどの既知のフォルダーを使用してメディア ライブラリにアクセスし、ストリーム メソッドを使用してメディア ライブラリにファイルを追加する場合は、コードが開くすべてのストリームを必ず閉じる必要があります。 それ以外の場合、少なくとも 1 つのストリームにファイルへのハンドルが残っているため、これらのメソッドは、期待どおりにファイルをメディア ライブラリに追加できません。

たとえば、次のコードを実行すると、ファイルはメディア ライブラリに追加されません。 コード行で、using (var destinationStream = (await destinationFile.OpenAsync(FileAccessMode.ReadWrite)).GetOutputStreamAt(0))OpenAsync メソッドと GetOutputStreamAt メソッドの両方がストリームを開きます。 ただし、GetOutputStreamAt メソッドによって開かれたストリームのみが、 ステートメントを使用した の結果として破棄されます。 他のストリームは開いたままで、ファイルの保存を妨げる。

StorageFolder testFolder = await StorageFolder.GetFolderFromPathAsync(@"C:\test");
StorageFile sourceFile = await testFolder.GetFileAsync("TestImage.jpg");
StorageFile destinationFile = await KnownFolders.CameraRoll.CreateFileAsync("MyTestImage.jpg");
using (var sourceStream = (await sourceFile.OpenReadAsync()).GetInputStreamAt(0))
{
    using (var destinationStream = (await destinationFile.OpenAsync(FileAccessMode.ReadWrite)).GetOutputStreamAt(0))
    {
        await RandomAccessStream.CopyAndCloseAsync(sourceStream, destinationStream);
    }
}

ストリーム メソッドを使用してメディア ライブラリにファイルを追加するには、次の例に示すように、コードが開くすべてのストリームを閉じてください。

StorageFolder testFolder = await StorageFolder.GetFolderFromPathAsync(@"C:\test");
StorageFile sourceFile = await testFolder.GetFileAsync("TestImage.jpg");
StorageFile destinationFile = await KnownFolders.CameraRoll.CreateFileAsync("MyTestImage.jpg");

using (var sourceStream = await sourceFile.OpenReadAsync())
{
    using (var sourceInputStream = sourceStream.GetInputStreamAt(0))
    {
        using (var destinationStream = await destinationFile.OpenAsync(FileAccessMode.ReadWrite))
        {
            using (var destinationOutputStream = destinationStream.GetOutputStreamAt(0))
            {
                await RandomAccessStream.CopyAndCloseAsync(sourceInputStream, destinationStream);
            }
        }
    }
}