共用方式為


音樂、圖片及影片媒體櫃中的檔案和資料夾

將現有的音樂、圖片或影片資料夾新增至對應的文件庫。 您也可以從媒體櫃中移除資料夾、取得媒體櫃中的資料夾清單,以及尋找已儲存的相片、音樂和影片。

媒體櫃是資料夾的虛擬集合,其中預設會包含已知資料夾,以及使用者已使用您的應用程式或其中一個內建應用程式新增至媒體櫃的任何其他資料夾。 例如,圖片庫預設會包含 [圖片] 已知資料夾。 使用者可以使用您的應用程式或內建的 Photos 應用程式,將資料夾新增至圖片庫,或將資料夾從圖片庫中移除。

必要條件

  • 了解通用 Windows 平台 (UWP) 應用程式的非同步程式設計

    您可以參閱在 C# 或 Visual Basic 中呼叫非同步 API,以了解如何使用 C# 或 Visual Basic 撰寫非同步的應用程式。 若要了解如何使用 C++ 撰寫非同步的應用程式,請參閱 C++ 的非同步程式設計

  • 位置的存取權限

    在 Visual Studio 中,開啟資訊清單設計工具中的應用程式資訊清單檔案。 在 [功能] 頁面上,選取您應用程式所管理的媒體櫃。

    • 音樂媒體櫃
    • 圖片媒體櫃
    • 影片媒體櫃

    若要深入了解,請參閱檔案存取權限

取得程式庫的參考

注意

請記得宣告適當的功能。 如需詳細資訊,請參閱應用程式功能宣告 \(部分機器翻譯\)。  

若要取得使用者音樂庫、圖片庫或影片庫的參考,請呼叫 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 屬性中 (以及內建的 [圖片] 應用程式中) 的項目,但資料夾不會顯示為 [檔案總管] 中 [圖片] 資料夾的子系。

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

從媒體櫃移除資料夾

若要從媒體櫃移除資料夾,請呼叫 StorageLibrary.RequestRemoveFolderAsync 方法,並指定要移除的資料夾。 您可以使用 StorageLibrary.FoldersListView 控制項 (或類似項目),讓使用者選取要移除的資料夾。

當您呼叫 StorageLibrary.RequestRemoveFolderAsync 時,使用者會看到確認對話方塊,指出資料夾「不會再出現在圖片中,也不會刪除」。這表示資料夾會保留在磁碟的原始位置、從 StorageLibrary.Folders 屬性中移除,且不再包含在內建的 [相片] 應用程式中。

下列範例假設使用者已選取要從名為 lvPictureFoldersListView 控制項中移除的資料夾。

bool result = await myPictures.RequestRemoveFolderAsync(folder);

取得媒體櫃中資料夾清單變更的通知

若要收到媒體櫃中資料夾清單變更的通知,請註冊媒體櫃 StorageLibrary.DefinitionChanged 事件的處理常式。

myPictures.DefinitionChanged += MyPictures_DefinitionChanged;

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

媒體櫃資料夾

裝置提供五個預先定義的位置,供使用者和應用程式儲存媒體檔案。 內建應用程式會將使用者建立的媒體和下載的媒體儲存在這些位置。

位置如下:

  • 圖片資料夾。 包含圖片。

    • 手機相簿資料夾。 包含來自內建相機的相片和影片。

    • 已儲存的圖片資料夾。 包含使用者從其他應用程式儲存的圖片。

  • 音樂資料夾。 包含歌曲、播客和音訊書籍。

  • 影片資料夾。 包含影片。

使用者或應用程式也可以將媒體檔案儲存在媒體櫃資料夾之外的 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 等已知資料夾存取媒體櫃,並使用串流方法將檔案新增至媒體櫃時,您必須確定關閉程式碼開啟的所有串流。 否則,這些方法無法如預期般將檔案新增至媒體櫃,因為至少有一個串流仍具有檔案的控制碼。

例如,當您執行下列程式碼時,不會將檔案新增至媒體櫃。 在程式碼 using (var destinationStream = (await destinationFile.OpenAsync(FileAccessMode.ReadWrite)).GetOutputStreamAt(0)) 中,OpenAsync 方法和 GetOutputStreamAt 方法都會開啟串流。 不過,只有 GetOutputStreamAt 方法所開啟的串流會因 using 陳述式而處置。 另一個串流會保持開啟狀態,並避免儲存檔案。

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