Search code examples
iphoneipadavfoundationavplayer

AVPlayer And Local Files


I am building a MP3 player for iOS that plays audio files hosted on the web. I want to offer the ability to play the files offline so I have the files downloading using ASIHTTP but I am cannot seem to find info on initiallzing AVPlayer with a mp3 in the app documents directory. Has anyone done this before? Is it even possible?

*I posted an answer below that shows how to use the iOS AvPlayer for both local and http files. Hope this helps!


Solution

  • I decided to answer my own question because I felt like there is very little documentation on how to use the Apple provided AVPlayer for both local and stream (over http) files. To help understand the solution, I put together a sample project on GitHub in Objective-C and Swift The code below is Objective-C but you can download my Swift example to see that. It is very similar!

    What I found is that the two ways of setting up the files are almost identical except for how you instantiate your NSURL for the Asset > PlayerItem > AVPlayer chain.

    Here is an outline of the core methods

    .h file (partial code)

    -(IBAction) BtnGoClick:(id)sender;
    -(IBAction) BtnGoLocalClick:(id)sender;
    -(IBAction) BtnPlay:(id)sender;
    -(IBAction) BtnPause:(id)sender;
    -(void) setupAVPlayerForURL: (NSURL*) url;
    

    .m file (partial code)

    -(IBAction) BtnGoClick:(id)sender {
    
        NSURL *url = [[NSURL alloc] initWithString:@""];
    
        [self setupAVPlayerForURL:url];
    }
    
    -(IBAction) BtnGoLocalClick:(id)sender {
    
        // - - - Pull media from documents folder
    
        //NSString* saveFileName = @"MyAudio.mp3";
        //NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        //NSString *documentsDirectory = [paths objectAtIndex:0];
        //NSString *path = [documentsDirectory stringByAppendingPathComponent:saveFileName];
    
        // - - -
    
        // - - - Pull media from resources folder
    
        NSString *path = [[NSBundle mainBundle] pathForResource:@"MyAudio" ofType:@"mp3"];
    
        // - - -
    
        NSURL *url = [[NSURL alloc] initFileURLWithPath: path];
    
        [self setupAVPlayerForURL:url];
    }
    
    -(void) setupAVPlayerForURL: (NSURL*) url {
        AVAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil];
        AVPlayerItem *anItem = [AVPlayerItem playerItemWithAsset:asset];
    
        player = [AVPlayer playerWithPlayerItem:anItem];
        [player addObserver:self forKeyPath:@"status" options:0 context:nil];
    }
    
    
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    
        if (object == player && [keyPath isEqualToString:@"status"]) {
            if (player.status == AVPlayerStatusFailed) {
                NSLog(@"AVPlayer Failed");
            } else if (player.status == AVPlayerStatusReadyToPlay) {
                NSLog(@"AVPlayer Ready to Play");
            } else if (player.status == AVPlayerItemStatusUnknown) {
                NSLog(@"AVPlayer Unknown");
            }
        }
    }
    
    -(IBAction) BtnPlay:(id)sender {
        [player play];
    }
    
    -(IBAction) BtnPause:(id)sender {
        [player pause];
    }
    

    Check out the Objective-C source code for a working example of this. Hope this helps!

    -Update 12/7/2015 I now have a Swift example of the source code you can view here.