ios音乐播放器使用综述
问题有:
1. 关于网络上的数据流播放,之前是使用github上的AudioStream库进行网络歌曲的播放。但是这么做之后发现跟AVPlayer(播放ipod歌曲)发生冲突,于是AudioSteamer库就只能放弃了。
2. 关于ipod的歌曲播放,基本上无法操作ipod的歌曲,如果要通过dlna传送本机ipod的歌曲,那么必须先将ipod的歌转存到本地,这个过程比较麻烦,于是放弃了。
3. ipod的歌曲读取需要通过MediaPlayer、MediaItem来读取ipod的数据。
4. 在线音乐、流媒体、直播流都可以通过AVPlayer来播放,而不再使用AudioStreamer。
5. ipod的歌曲播放可以用MediaPlayer中的IpodPlayer来播放,但是保存方便还是使用AVPlayer。
6. AVPlayer可以播放本地歌曲,因此从网络下载的本地歌曲也可以是用这个来播放。
7. AVPlayer类有个子类,AVQueuePlayer,可以添加队列进行控制播放。
总结:音乐播放器必须使用AVPlayer,可以播放应用内保存的音乐,播放网络音乐,播放网络电台、播放ipod音乐,设置后台播放,设置封面,还可以创建播放队列。
关于AVPlayer的使用有几个问题:
1. 设置后台播放
在info.plist中需要添加Required background modes,并且添加值App plays audio
在应用的delegate中Launch函数里添加代码
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. { if([application respondsToSelector:@selector(beginReceivingRemoteControlEvents)]) [application beginReceivingRemoteControlEvents]; [self becomeFirstResponder]; // this enables listening for events [[AVAudioSessionsharedInstance] setCategory:AVAudioSessionCategory Playbackerror:nil]; [[AVAudioSessionsharedInstance] setActive: YES error: nil]; } return YES; } - (BOOL)canBecomeFirstResponder{ return YES; }
setCategory这个方法设定了这个应用的声音播放实例可以在后台播放,并且音频播放是可打断或被打断的。
delegate要继承UIResponser借口,beginReceivingControlEvents调用后就可以接受ipod control的消息。
becomeFirstResponder方法使用后会在ipod control有响应后将消失传递到这个类做响应。
2. 后台播放时,ipod control的点击事件响应。
在appdelegate中(因为设置成了响应者)加入响应代码
- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
switch (event.subtype) {
case UIEventSubtypeRemoteControlTogglePlayPause:
NSLog(@"play btn toggle");
break;
case UIEventSubtypeRemoteControlPlay:
NSLog(@"play event");
break;
case UIEventSubtypeRemoteControlPause:
NSLog(@"pause event");
break;
case UIEventSubtypeRemoteControlStop:
NSLog(@"stop event");
break;
case UIEventSubtypeRemoteControlPreviousTrack:
NSLog(@"prev event");
break;
case UIEventSubtypeRemoteControlNextTrack:
NSLog(@"next event");
break;
default:
break;
}
}
这里做音乐播放器后台ipod操作的响应控制。
3. 后台播放时,设置ipod control的封面图片,歌曲名等信息。通过设置当前媒体播放器的信息来实现。
在应用弹出去或者歌曲切换事件出发的时候调用该函数。
- (void)configNowPlayingInfoCenter {
if (NSClassFromString(@"MPNowPlayingInfoCenter")) {
MPNowPlayingInfoCenter *center = [MPNowPlayingInfoCenter defaultCenter];
UIImage *image = [UIImage imageNamed:@"figo.png"];
MPMediaItemArtwork *artwork = [[MPMediaItemArtwork alloc] initWithImage:image];
NSDictionary*songInfo = [NSDictionary dictionaryWithObjectsAndKeys:
@"华哥", MPMediaItemPropertyArtist,
@"嘿嘿", MPMediaItemPropertyTitle,
artwork, MPMediaItemPropertyArtwork,
@"嘿嘿", MPMediaItemPropertyAlbumTitle,
nil];
center.nowPlayingInfo = songInfo;
}
}
在这些时候可以触发:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[self configNowPlayingInfoCenter];
}
-(void)playerItemDidReachEnd:(NSNotification *)notification {
[self configNowPlayingInfoCenter];
}
4. 音乐播放队列的播放顺序是通过监听音乐播放结束或开始,再做相应的处理,在appdelegat中监听事件。这些事件需要Audio框架中开启。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification object:[player currentItem]];
监听这些事件后,进行播放队列调整。或者是ipod control切换歌曲的时候调整ipod封面和歌名。
5. 使用AVPlayer播放歌曲
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification object:[player currentItem]];
AVPlayerItem *item1 = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:@"http://192.168.1.127/5.mp3"]];
AVPlayerItem *item2 = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:@"http://192.168.1.127/1.mp3"]];
AVPlayerItem *item3 = [AVPlayerItem playerItemWithAsset:[AVAsset assetWithURL:[NSURL URLWithString:@"http://shoutmedia.abc.net.au:10326"]]];
AVPlayerItem *item4 = [AVPlayerItem playerItemWithAsset:[AVAsset assetWithURL:[NSURL URLWithString:@"http://192.168.1.127/1.mp3"]]];
NSArray *items = @[item3,item4];
queuePlayer = [AVQueuePlayer queuePlayerWithItems:items];
[queuePlayer play];
有队列,通过事件回调控制封面和播放顺序的方式。
6. 播放ipod的歌曲
要使用Mediaplayer库,Audio库
MPMediaQuery *myPlaylistsQuery = [MPMediaQuery songsQuery];
NSArray *playlists = [myPlaylistsQuery collections];
GDSongNet *newSong;
NSMutableArray *array = [[NSMutableArray alloc] init];;
for (MPMediaPlaylist *playlist in playlists) {
newSong = nil;
newSong = [[GDSongNet alloc] init];
NSArray *songs = [playlist items];
for (MPMediaItem *song in songs) {
newSong.songStatusType = [NSNumber numberWithInt:PLAYER_LOCAL];
newSong.songCoverUrl = @"/Public/Images/nopic_80x80.jpg";
newSong.songMusic_id = [song valueForProperty:MPMediaItemPropertyPersistentID];//MPMediaItemPropertyPersistentID
newSong.songMusic_name = [song valueForProperty:MPMediaItemPropertyTitle];
newSong.songSinger = [song valueForProperty:MPMediaItemPropertyArtist];//
newSong.songType_id = [NSNumber numberWithInt:1];
newSong.songUrl = [song valueForProperty:MPMediaItemPropertyAssetURL];
[array addObject:newSong];
}
}
self.localMusics = array;
7. AVPlayer检索元数据
元数据的数组:
NSArray *metaDatas = [[[mPlayercurrentItem] asset] commonMetadata];
遍历获取数据
for (AVMetadataItem* item in mMetadata)
{
NSString* commonKey = [item commonKey];
if ([commonKey isEqualToString:AVMetadataCommonKeyTitle])
{
[mTitleLabel setText:[item stringValue]];
[mTitleLabel setHidden:NO];
}
if ([commonKey isEqualToString:AVMetadataCommonKeyCopyrights])
{
[mCopyrightLabel setText:[item stringValue]];
[mCopyrightLabel setHidden:NO];
}
}
附件:测试项目
浙公网安备 33010602011771号