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

 

 

 

 附件:测试项目

posted @ 2012-12-20 22:25  chemandy  阅读(506)  评论(0编辑  收藏  举报