音樂、圖片及影片媒體櫃中的檔案和資料夾Files and folders in the Music, Pictures, and Videos libraries

將現有的音樂、圖片或視訊資料夾新增到對應的媒體櫃中。Add existing folders of music, pictures, or videos to the corresponding libraries. 您也可以從媒體櫃中移除資料夾、取得媒體櫃中的資料夾清單,以及尋找已儲存的相片、音樂和影片。You can also remove folders from libraries, get the list of folders in a library, and discover stored photos, music, and videos.

媒體櫃是一個虛擬資料夾集合,依預設會包含已知的資料夾,外加使用者透過您的 app 或其中一個內建 app 新增至媒體櫃的任何其他資料夾。A library is a virtual collection of folders, which includes a known folder by default plus any other folders the user has added to the library by using your app or one of the built-in apps. 例如,圖片媒體櫃依預設會包含 [圖片] 這個已知資料夾。For example, the Pictures library includes the Pictures known folder by default. 使用者可以透過您的 app 或內建的 [相片] app,在圖片媒體櫃中新增或移除資料夾。The user can add folders to, or remove them from, the Pictures library by using your app or the built-in Photos app.

必要條件Prerequisites

  • 了解通用 Windows 平台 (UWP) 應用程式的非同步程式設計Understand async programming for Universal Windows Platform (UWP) apps

    您可以參閱在 C# 或 Visual Basic 中呼叫非同步 API,以了解如何使用 C# 或 Visual Basic 撰寫非同步的 app。You can learn how to write asynchronous apps in C# or Visual Basic, see Call asynchronous APIs in C# or Visual Basic. 若要了解如何使用 C++ 撰寫非同步的 App,請參閱 C++ 的非同步程式設計To learn how to write asynchronous apps in C++, see Asynchronous programming in C++.

  • 位置的存取權限Access permissions to the location

    在 Visual Studio 中,於「資訊清單設計工具」中開啟 app 資訊清單檔案。In Visual Studio, open the app manifest file in Manifest Designer. 在 [功能] 頁面上,選取您應用程式所管理的媒體櫃。On the Capabilities page, select the libraries that your app manages.

    • 音樂媒體櫃Music Library
    • 圖片媒體櫃Pictures Library
    • 影片媒體櫃Videos Library

    若要深入了解,請參閱檔案存取權限To learn more, see File access permissions.

取得對媒體櫃的參考Get a reference to a library

注意

請記得宣告適當的功能。Remember to declare the appropriate capability. 如需詳細資訊,請參閱應用程式功能宣告 (部分機器翻譯)。See App capability declarations for more information.  

若要取得對使用者的 [音樂]、[圖片] 或 [影片] 媒體櫃的參考,請呼叫 StorageLibrary.GetLibraryAsync 方法。To get a reference to the user's Music, Pictures, or Video library, call the StorageLibrary.GetLibraryAsync method. KnownLibraryId 列舉提供對應的值。Provide the corresponding value from the KnownLibraryId enumeration.

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

取得媒體櫃中資料夾的清單Get the list of folders in a library

若要取得媒體櫃中資料夾的清單,請取得 StorageLibrary.Folders 屬性的值。To get the list of folders in a library, get the value of the StorageLibrary.Folders property.

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

取得媒體櫃中預設儲存新檔案的資料夾Get the folder in a library where new files are saved by default

若要取得媒體櫃中預設儲存新檔案的資料夾,請取得 StorageLibrary.SaveFolder 屬性的值。To get the folder in a library where new files are saved by default, get the value of the StorageLibrary.SaveFolder property.

Windows.Storage.StorageFolder savePicturesFolder = myPictures.SaveFolder;

將現有的資料夾新增到媒體櫃Add an existing folder to a library

若要將資料夾新增至媒體櫃,您可以呼叫 StorageLibrary.RequestAddFolderAsyncTo add a folder to a library, you call the StorageLibrary.RequestAddFolderAsync. 以圖片媒體櫃為例,呼叫此方法時會隨即對使用者顯示資料夾選擇器,並出現 [將此資料夾新增至圖片] 按鈕。Taking the Pictures Library as an example, calling this method causes a folder picker to be shown to the user with an Add this folder to Pictures button. 如果使用者挑選一個資料夾,則該資料夾會保留在磁碟的原始位置上,且成為 StorageLibrary.Folders 屬性 (和內建的 [相片] app) 中的項目,但是該資料夾不會顯示為檔案總管中 [圖片] 資料夾的子項。If the user picks a folder then the folder remains in its original location on disk and it becomes an item in the StorageLibrary.Folders property (and in the built-in Photos app), but the folder does not appear as a child of the Pictures folder in File Explorer.

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

從媒體櫃中移除資料夾Remove a folder from a library

若要從媒體櫃中移除資料夾,請呼叫 StorageLibrary.RequestRemoveFolderAsync 方法,並指定要移除的資料夾。To remove a folder from a library, call the StorageLibrary.RequestRemoveFolderAsync method and specify the folder to be removed. 您可以使用 StorageLibrary.FoldersListView 控制項 (或類似項目),讓使用者選取要移除的資料夾。You could use StorageLibrary.Folders and a ListView control (or similar) for the user to select a folder to remove.

當您呼叫 StorageLibrary.RequestRemoveFolderAsync 時,使用者會看到確認對話方塊,指出資料夾「不會再出現在 [圖片] 中,但也不會被刪除」。When you call StorageLibrary.RequestRemoveFolderAsync, the user sees a confirmation dialog saying that the folder "won't appear in Pictures anymore, but won't be deleted." 這表示,資料夾仍保留在磁碟的原始位置上、已從 StorageLibrary.Folders 屬性中移除,且將不再包含在內建的 [相片] app 中。What this means is that the folder remains in its original location on disk, is removed from the StorageLibrary.Folders property, and will no longer included in the built-in Photos app.

下列範例假設使用者已從名為 lvPictureFoldersListView 控制項中選取要移除的資料夾。The following example assumes that the user has selected the folder to remove from a ListView control named lvPictureFolders.

bool result = await myPictures.RequestRemoveFolderAsync(folder);

取得媒體櫃中資料夾清單變更的通知Get notified of changes to the list of folders in a library

若要取得與媒體櫃中資料夾清單變更相關的通知,請為媒體櫃的 StorageLibrary.DefinitionChanged 事件註冊一個處理常式。To get notified about changes to the list of folders in a library, register a handler for the StorageLibrary.DefinitionChanged event of the library.

myPictures.DefinitionChanged += MyPictures_DefinitionChanged;

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

媒體櫃資料夾Media library folders

裝置會為使用者和 app 提供五個預先定義的位置來儲存媒體檔案。A device provides five predefined locations for users and apps to store media files. 內建 app 會將使用者建立的媒體和下載的媒體都儲存在這些位置。Built-in apps store both user-created media and downloaded media in these locations.

這些位置包括:The locations are:

  • [圖片] 資料夾。Pictures folder. 包含圖片。Contains pictures.

    • [手機相簿] 資料夾。Camera Roll folder. 包含內建相機中的相片和視訊。Contains photos and video from the built-in camera.

    • [儲存的圖片] 資料夾。Saved Pictures folder. 包含使用者從其他 app 儲存的圖片。Contains pictures that the user has saved from other apps.

  • [音樂] 資料夾。Music folder. 包含歌曲、播客和有聲書。Contains songs, podcasts, and audio books.

  • [影片] 資料夾。Video folder. 包含視訊。Contains videos.

使用者或應用程式也可以將媒體檔案儲存在媒體櫃資料夾以外的 SD 記憶卡上。Users or apps may also store media files outside the media library folders on the SD card. 若要尋找確實在 SD 記憶卡上的媒體檔案,請掃描 SD 記憶卡的內容,或要求使用者使用檔案選擇器來找出檔案。To find a media file reliably on the SD card, scan the contents of the SD card, or ask the user to locate the file by using a file picker. 如需詳細資訊,請參閱存取 SD 記憶卡For more info, see Access the SD card.

查詢媒體櫃Querying the media libraries

若要取得檔案集合,指定媒體櫃及您要的檔案類型To get a collection of files, specify the library and the type of files that you want.

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

查詢結果同時包含內部和卸除式儲存空間Query results include both internal and removable storage

使用者可以選擇預設將檔案儲存到選用的 SD 記憶卡。Users can choose to store files by default on the optional SD card. 不過,應用程式可以選擇不允許將檔案儲存到 SD 記憶卡。Apps, however, can opt out of allowing files to be stored on the SD card. 因此,媒體櫃可以分割到裝置的內部儲存空間及 SD 記憶卡上。As a result, the media libraries can be split across the device's internal storage and the SD card.

您不需要編寫其他程式碼即可處理這項操作。You don't have to write additional code to handle this possibility. Windows.Storage 命名空間中明確查詢已知資料夾的方法會結合來自這兩個位置的查詢結果。The methods in the Windows.Storage namespace that query known folders transparently combine the query results from both locations. 您不需要在 app 資訊清單檔案中指定 removableStorage 功能,即可取得這些結合的結果。You don't have to specify the removableStorage capability in the app manifest file to get these combined results, either.

考量下圖中裝置儲存空間的狀態:Consider the state of the device's storage shown in the following image:

電話和 SD 記憶卡的影像

如果您透過呼叫 await KnownFolders.PicturesLibrary.GetFilesAsync() 來查詢圖片媒體櫃的內容,結果會包含 internalPic.jpg 與 SDPic.jpg 兩者。If you query the contents of the Pictures Library by calling await KnownFolders.PicturesLibrary.GetFilesAsync(), the results include both internalPic.jpg and SDPic.jpg.

使用相片Working with photos

如果裝置的相機會同時儲存每張圖片的低解析度影像和高解析度影像,則深層查詢只會傳回低解析度影像。On devices where the camera saves both a low-resolution image and a high-resolution image of every picture, the deep queries return only the low-resolution image.

[手機相簿] 和 [儲存的圖片] 資料夾不支援深層查詢。The Camera Roll and the Saved Pictures folder do not support the deep queries.

在拍攝相片的應用程式中開啟該相片Opening a photo in the app that captured it

如果您想要讓使用者稍後可以在拍攝相片的 app 中再次開啟該相片,您可以使用與下列範例類似的程式碼,將 CreatorAppId 與相片的中繼資料儲存在一起。If you want to let the user open a photo again later in the app that captured it, you can save the CreatorAppId with the photo's metadata by using code similar to the following example. 在此範例中,testPhotoStorageFileIn this example, testPhoto is a StorageFile.

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

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

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

使用串流方法將檔案新增到媒體櫃Using stream methods to add a file to a media library

當您使用已知資料夾來存取媒體櫃 (例如 KnownFolders.PictureLibrary),並且使用串流方法將檔案新增到媒體櫃時,請務必關閉您的程式碼所開啟的所有串流。When you access a media library by using a known folder such as KnownFolders.PictureLibrary, and you use stream methods to add a file to the media library, you have to make sure to close all the streams that your code opens. 否則,這些方法將無法如預期般將檔案新增到媒體櫃,因為至少還有一個串流仍然擁有檔案的控制代碼。Otherwise these methods fail to add the file to the media library as expected because at least one stream still has a handle to the file.

舉例來說,當您執行下列程式碼時,系統並不會將檔案新增到媒體櫃。For example, when you run the following code, the file is not added to the media library. using (var destinationStream = (await destinationFile.OpenAsync(FileAccessMode.ReadWrite)).GetOutputStreamAt(0)) 程式碼行中,OpenAsync 方法和GetOutputStreamAt 方法皆開啟了一個串流。In the line of code, using (var destinationStream = (await destinationFile.OpenAsync(FileAccessMode.ReadWrite)).GetOutputStreamAt(0)), both the OpenAsync method and the GetOutputStreamAt method open a stream. 不過,由於 using 陳述式,系統只會處置 GetOutputStreamAt 方法所開啟的串流。However only the stream opened by the GetOutputStreamAt method is disposed as a result of the using statement. 另一個串流會保持開啟,而導致無法儲存檔案。The other stream remains open and prevents saving the file.

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

若要順利使用串流方法將檔案新增到媒體櫃,請務必關閉您的程式碼所開啟的所有串流,如下列範例所示。To use stream methods successfully to add a file to the media library, make sure to close all the streams that your code opens, as shown in the following example.

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