現在市面上的音樂播放器都支持iPod Library歌曲(俗稱iPod音樂或者本地音樂)的播放,用戶對於iPod音樂播放的需求也一直十分強烈。這篇要講的是如何來播放iPod Library的歌曲。
概述
根據官方文檔描述Apple從iOS 3.0開始允許開發者訪問用戶的iPod library來獲取用戶放在其中的歌曲等多媒體內容。
爲此Apple提供了多種方法來訪問和播放iPod中的音樂,下面我們來分別列舉一下這些方法。
訪問MediaLibrary
官方文檔訪問iPod Library的方法有兩種,分別是MediaPicker和MediaQuery。
MediaPicker
MediaPicker是一個高度封裝的iPod Library訪問方式,通過使用MPMediaPickerController
類來訪問iPod
Library。這是一個UI控件,用戶可以根據需要選擇其中的音樂。這個類使用時非常方便,只需要生成一個“的實例,設置一下屬性和delegate後present出來,接下來只要等待回調即可,在回調時需要手動dismiss picker。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
上面的代碼將會得到如下的效果:
通過MediaPicker最終可以得到MPMediaItemCollection
,其中存放着所有在Picker中選中的歌曲,每一個歌曲使用一個MPMediaItem
對象表示。對於MediaPicker的使用也可以參考官方文檔。
MediaQuery
如果你覺得MeidaPicker的功能或者UI不能滿足你的要求那麼可以使用MediaQuery。MediaQuery可以直接訪問iPod Library的DB,並根據需要獲取數據。官方文檔給出了MediaQuery的示意圖。
MediaQuery功能十分強大,它可以根據一個或多個條件查詢滿足需要的MediaItem。
你可以使用MPMediaQuery
的類方法來生成一些已經預置了條件的Query
1 2 3 4 5 6 7 8 9 10 11 |
|
也可以自己生成MPMediaPredicate
設置條件,並把它加到Query中,最後通過items和collections訪問查詢到的結果,例如:
1 2 3 4 5 6 7 8 9 10 11 |
|
這一過程可以表示爲(圖來自官方文檔):
這裏對於MediaQuery的用法就不再繼續展開,關於這塊內容並沒有什麼晦澀難懂的地方需要解釋,大家可以通過閱讀官方文檔來詳細瞭解其用法。
MediaCollection
MPMediaCollection
是MediaItem的合集,可以通過訪問它的items屬性來訪問所有的MediaItem。
MPMediaPlaylist
是一個特殊的MPMediaCollection
代表用戶創建的播放列表,它會比MediaCollection包含更多的信息,比如播放列表的名字等等。這些屬性可以通過MPMediaEntity
的方法訪問(MPMediaCollection是MPMediaEntity的子類,MPMediaItem也是)。
1 2 3 4 5 6 7 |
|
MediaItem
通過MediaPicker和MediaQuery最終都會得到MPMediaItem
,這個item中包含了許多信息。這些信息都可以通過MPMediaEntity
的方法訪問,其中參數非常多就不列舉了具體可以參照MPMediaItem.h。
使用MPMusicPlayerController
拿到iPod Library中的歌曲後就可以開始播放了。播放的方式有很多種,先介紹一下MediaPlayer
framework
中的MPMusicPlayerController
類。
通過MPMusicPlayerController
的類方法可以生成兩種播放器,生成方法如下:
1 2 3 4 5 |
|
這兩個方法看似生成了一樣的對象,但它們的行爲卻有很大不同。從Apple寫的註釋上我們可以很清楚的發現它們的區別。+applicationMusicPlayer
不會繼承來自iOS系統自帶的iPod應用中的播放狀態,同時也不會覆蓋iPod的播放狀態。而+iPodMusicPlayer
完全繼承iPod應用的播放狀態(甚至是播放時間),對其實例的任何操作也會覆蓋到iPod應用。對+iPodMusicPlayer
方法command+點擊後可以看到更詳細的註釋。
1 2 3 4 5 6 7 |
|
說白了,當在使用iPodMusicPlayerv其實並不是你的程序在播放音頻,而是你的程序在操縱iPod應用播放音頻,即使你的程序crash了或者被kill了,音樂也不會因此停止。
而對於+applicationMusicPlayer
通過command+點擊可以看到:
1 2 |
|
從註釋中可以知道這個方法返回的對象雖然不是調用iPod應用播放的也不會影響到iPod應用,但它有個很大的缺點:無法後臺播放,即使你在active了audioSession並且在app的設置中設置了Background Audio同樣不會奏效。
綜上所述,一般在開發音樂軟件時很少用到這兩個接口來進行iPod Library的播放,大部分開發者都是用這個類中的volme來調整系統音量的(這個屬性在SDK 7中也被deprecate掉了)。如果你想用到這個類進行播放的話,這裏需要提個醒,給MPMusicPlayerController
設置需要播放的音樂時要使用下面兩個方法:
1 2 3 |
|
而不是這個屬性:
1 2 3 |
|
光看名字很容易被nowPlayingItem
這個屬性迷惑,它的意思其實是說在設置了MediaQuery或者MediaCollection之後再設置這個nowPlayingItem可以讓播放器從這個item開始播放,前提是這個item需要在MediaQuery或者MediaCollection的.items集合內。
使用AVAudioPlayer和AVPlayer
除了使用MediaPlayer中的類還有很多其他方法來進行iPod播放,其中做的比較出色的是AVFoundation
中的AVAudioPlayer
和AVPlayer
。
這兩個類的都有通過NSURL生成實例的初始化方法:
1 2 3 4 5 6 |
|
其中的NSURL正是來自於MPMediaItem
的MPMediaItemPropertyAssetURL
屬性。
1 2 3 4 |
|
上面講到MPMediaItem
時已經提到了它是MPMediaEntity
子類,可以通過-valueForProperty:
方法訪問其中的屬性。通過傳入MPMediaItemPropertyAssetURL
就可以得到當前MediaItem對應的URL(ipod-library://xxxxx),生成Player進行播放。大致代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
注意:這裏我需要更正一下,之前我在第二篇講到AudioSession時寫了這樣一段話在使用AVAudioPlayer/AVPlayer時可以不用關心AudioSession的相關問題,Apple已經把AudioSession的處理過程封裝了...
。這段話不對,我把AVFoundation和Mediaplayer混淆了,在寫的時候也沒注意,應該是在使用MPMusicPlayerController播放時不需要關心AudioSession的問題。
讀取和導出數據
前面說到使用MPMediaItem
的MPMediaItemPropertyAssetURL
屬性可以得到一個表示當前MediaItem的NSURL,有了這個NSURL我們使用AVFoundation中的類進行播放。播放只是最基本的需求,有了這個URL我們可以做更多更有趣的事情。
在AVFoundation中還有兩個有趣的類:AVAssetReader
和AVAssetExportSession
。它們可以把iPod
Library中的指定歌曲以指定的音頻格式導出到內存中或者硬盤中,這個指定的格式包括PCM。這是一個激動人心的特性,有了PCM數據我們就可以做很多很多其他的事情了。
這部分如果要展開的話還會有相當多的內容,國外的先輩們早在2010年就已經發掘了這兩個類的用法,詳細參見這裏和這裏。這兩篇講的比較詳細並且附有Sample(其中還涉及了一些Extended Audio File Services的內容),如果裏面Sample無法下載可以從點擊MediaLibraryExportThrowaway1.zip和VTM_AViPodReader.zip下載。
需要注意的是在使用AVAssetReader
的過程中如果訪問系統的相機或者照片可能會使AVAssetReader
產生AVErrorOperationInterrupted
錯誤,此時需要重新生成Reader後調用-startReading
纔可以繼續讀取數據。
小結
本篇介紹了一些與iPod Library相關的內容,小結一下:
-
Apple提供兩種方法來訪問iPod Library,它們分別是
MPMediaPickerController
和MPMediaQuery
; -
MPMediaPickerController
和MPMediaQuery
最後輸出給開發者的對象是MPMediaItem
,MPMediaItem
的屬性需要通過-valueForProperty:
方法獲取了; -
MPMusicPlayerController
可以用來播放MPMediaItem
,但有很多侷限性,使用時需要根據不同的使用場景來決定用哪個類方法生成實例; -
AVAudioPlayer
和AVPlayer
也可以用來播放MPMediaItem
,這兩個類的功能比較完善,推薦使用,在使用之前別忘記設置AudioSession; -
MPMediaItem
可以得到對應的URL,這個URL可以用來做很多事情,例如用AVAssetReader
和AVAssetExportSession
可以導出其中的數據;