转载自:iOS音频播放 (七):播放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
可以导出其中的数据;